[swift-evolution] [Proposal idea] Improved interop for ErrorType->NSError

Brent Royal-Gordon brent at architechies.com
Sun Dec 20 00:35:16 CST 2015

> Unfortunately, the Cocoa APIs needed to display an error object to the user all take NSErrors, and the conversion from other ErrorTypes to NSErrors is not very good; using “as NSError” to convert a MyError will result in something that has all of the associated values removed, and the message displayed to the user will be a cryptic and not particularly user-friendly “MyError error 1” rather than something more descriptive.

I too badly want to be able to control the `userInfo` of an NSError, or at least have casting to NSError and back round-trip nicely.

> One can define an “toNSError()” method on one’s own error type that will properly propagate the NSError’s userInfo dictionary such that it will be displayed in a more meaningful way:

This, however, seems like a recipe for boilerplate.

What I would like to see is this:

* `var userInfo: [String: AnyObject] { get }` is added to `ErrorType`, or perhaps to a sub-protocol specifically for this purpose. There's a default implementation which simply returns `[:]`.

* A type like this exists in the standard library, or perhaps the Foundation overlay:

	private class _NSSwiftError: NSError {
		var swiftError: ErrorType
		init(swiftError: ErrorType) {
			self.swiftError = swiftError
			super.init(domain: swiftError.domain, code: swiftError.code, userInfo: swiftError.userInfo)

I don't know if it can actually be private, but it should be invisible to developers, and considered an implementation detail. It might also make sense to retrieve the `userInfo` from `swiftError` on demand—the exact implementation isn't very important here.

* Casting a native Swift error enum to `NSError` actually constructs an `_NSSwiftError`. (Bridged error code enums like `NSCocoaError` use `NSError` as usual.)

* Casting an `_NSSwiftError` back to `ErrorType` or a native Swift `ErrorType` enum pulls the original instance back out of `swiftError`, so all associated objects are preserved. (Bridged error code enums just construct a new instance.)

This way, the only code you have to write is a `userInfo` implementation, and even that only if you want to do something custom. There's no need to write a bunch of code to construct an entire `NSError` instance, or to unpack the `userInfo` back into a Swift enum.

Brent Royal-Gordon

More information about the swift-evolution mailing list