Making your own errors in Swift

Swift’s Error protocol is commonly used across Apple’s APIs to represent failure states.

Typically, it’s used like this:

HKHealthStore().disableAllBackgroundDelivery { (success, errorOrNil) in
  if let error = errorOrNil {
    print(error.localizedDescription)
  }
}

Example of an Error that can be returned from a HealthKit method.

Recently I wanted to create my own instance of Error, like this:

func doSomethingAsync(onComplete: @escaping (Bool, Error?) -> Void) {
  let result = SomeClass.methodThatMightCauseError()
  if result {
      onComplete(true, nil)
  } else {
      onComplete(false, Error("Failed to do the thing"))
  }
}

Because Error is a protocol, it cannot be constructed directly and the above code won’t work. To fix it, we need to make a simple struct that implements the protocol, like this:

struct AppError {
  let message: String

  init(_ message: String) {
    self.message = message
  }
}

extension AppError: LocalizedError {
  var errorDescription: String? { return message }
}

Now, the code from earlier can be changed to make an instance of AppError:

onComplete(false, AppError("Failed to do the thing"))

Credit to Reimond Hill on StackOverflow for pointing me in the right direction here.

And that’s it. This is pretty much the simplest implementation of Error you could make. It’ll work fine for trivial uses, but you may wish to implement more of the procotol for more robust error handling, for example be adding recovery suggestions, help anchors and error codes. Those are out of scope for this post, but Apple’s own documentation is a good place to go from if you’d like to learn more.

Thanks for reading.

To get in touch, email me or find me on Mastodon or Twitter.

If you liked this post, you'll love my iOS apps. Check them out below.

Personal Best

Level up your workouts

Taylor's Version

Upgrade Taylor Swift songs in your playlists

SalaryPig

Meet Trevor, the salary-tracking pig

Taylor Swift Quiz

How well do you know Taylor Swift?