Creating custom error types is an important skill when designing clear APIs for iOS and macOS applications. This post presents examples for creating, extending, throwing, and catching custom error types in Swift:
- Create A Custom Error And Conform To The Error Type
- Extend A Custom Error
- description for Custom Errors Using CustomStringConvertible
- localizedDescription For Custom Errors Using LocalizedError
- Throw Custom Errors
- Catch Custom Errors
Create A Custom Error And Conform To The Error Type
To create a custom error, create an enum
in Swift that conforms to the Error
protocol. Each case of the enum represents a unique error that can be thrown and handled:
enum CustomError: Error {
// Throw when an invalid password is entered
case invalidPassword
// Throw when an expected resource is not found
case notFound
// Throw in all other cases
case unexpected(code: Int)
}
Extend A Custom Error
Like all Swift types, new custom error types you create can be extended to add computed properties and functions. In this example, the isFatal
computed property is added that can be used to determine if the error is recoverable:
extension CustomError {
var isFatal: Bool {
if case CustomError.unexpected = self { return true }
else { return false }
}
}
description for Custom Errors Using CustomStringConvertible
Custom errors implemented in Swift can have custom descriptions for each error. To add a description to a new error type, extend the custom error to conform to CustomStringConvertible
and add a property description
:
// For each error type return the appropriate description
extension CustomError: CustomStringConvertible {
public var description: String {
switch self {
case .invalidPassword:
return "The provided password is not valid."
case .notFound:
return "The specified item could not be found."
case .unexpected(_):
return "An unexpected error occurred."
}
}
}
localizedDescription For Custom Errors Using LocalizedError
New custom errors you create in Swift can also have localized custom descriptions for each error. To add a localized description to a new error type, extend the custom error to conform to LocalizedError
and add a property errorDescription
:
// For each error type return the appropriate localized description
extension CustomError: LocalizedError {
public var errorDescription: String? {
switch self {
case .invalidPassword:
return NSLocalizedString(
"The provided password is not valid.",
comment: "Invalid Password"
)
case .notFound:
return NSLocalizedString(
"The specified item could not be found.",
comment: "Resource Not Found"
)
case .unexpected(_):
return NSLocalizedString(
"An unexpected error occurred.",
comment: "Unexpected Error"
)
}
}
}
Throw Custom Errors
Functions marked as throws
in Swift can throw custom errors directly:
func isAvailable(resourcePath path: String) throws -> Bool {
if FileManager.default.fileExists(atPath: path) {
return true
}
else {
throw CustomError.notFound
}
}
Catch Custom Errors
Custom errors can be individually caught and handled using the do
catch
syntax. Use catch
followed by the specific error to catch the error and apply specific handling logic:
func open(resourcePath: String) {
do {
try isAvailable(resourcePath: resourcePath)
// Handle opening the resource
}
catch CustomError.notFound {
// Handle custom error
}
catch {
// Handle other errors
}
}
Create Your Own Errors In Swift
That’s it! By conforming to Error
, CustomStringConvertible
, and LocalizedError
you can implement descriptive, clear, and actionable custom errors in Swift.