Ben Lu Ben Lu - 4 months ago 27
Swift Question

Converting ErrorType to NSError loses associated objects

In Swift 2.0

NSError
conforms to the
ErrorType
protocol.

For a customly defined error, we can specify the associating object(s) for some cases, like below.

enum LifeError: ErrorType {
case BeBorn
case LostJob(job: String)
case GetCaughtByWife(wife: String)
...
}


We can comfortably do the following:

do {
try haveAffairWith(otherPerson)
} catch LifeError.GetCaughtByWife(let wife) {
...
}


However if we want it to pass into other places as an
NSError
, it loses its associating object information.

println("\(LifeError.GetCaughtByWife("Name") as NSError)")


prints:

Error Domain=... Code=1 "The operation couldn't be completed". (... error 1)


and its
userInfo
is
nil
.

Where is my
wife
associated with the
ErrorType
?

Answer

An ErrorType can't really be casted to an NSError, you have to take the associated data and package it into an NSError yourself.

do {
    try haveAffairWith(otherPerson)
} catch LifeError.GetCaughtByWife(let wife) {
    throw NSError(domain:LifeErrorDomain code:-1 userInfo:
        [NSLocalizedDescriptionKey:"You cheated on \(wife)")
}

EDIT: Actually you can do the cast from ErrorType to NSError, but the NSError you get from the default implementation is quite primitive. What I'm doing in my app is hooking application:willPresentError: in my app delegate and using a custom class to read the my app's ErrorType's and decorate NSErrors to return.