[swift-evolution] [Review] SE-0112: Improved NSError Bridging

Ben Rimmington me at benrimmington.com
Tue Jul 5 19:54:34 CDT 2016


> On 6 Jul 2016, at 01:02, Douglas Gregor <dgregor at apple.com> wrote:
> 
>> On Jul 5, 2016, at 5:00 PM, Ben Rimmington <me at benrimmington.com> wrote:
>> 
>> <https://github.com/apple/swift-evolution/blob/master/proposals/0112-nserror-bridging.md>
>> 
>> The new protocols could be combined into a single CustomNSError protocol.
>> This would mirror the NSError class APIs, which are being customized.
> 
> Why is that good? The two primary protocols—LocalizedError and RecoverableError—provide a more focused, easy-to-understand experience for opting in to specific behavior. CustomNSError is a fallback for “I want to do something special with the generated NSError”.

You wrote previously:
"To a close approximation, there are no use sites of these protocols."
<http://thread.gmane.org/gmane.comp.lang.swift.evolution/22485/focus=22919>

If the Printable protocol was renamed to CustomStringConvertible to discourage use sites, then having a single CustomNSError protocol should have a similar effect. The protocol will be as easy-to-understand as the NSError class itself. If there are default implementations for all requirements, a conforming type can still opt into specific behavior.

>> Instead of using NSError.setUserInfoValueProvider(forDomain:provider:) 
>> could you wrap the CustomNSError value inside an NSError subclass?
>> 
>> 	class _CustomNSError: NSError {
>> 
>> 	    private let _error: CustomNSError
>> 
>> 	    init(_error: CustomNSError) {
>> 	        self._error = _error
>> 	        super.init(
>> 	            domain:   _error.dynamicType.errorDomain,
>> 	            code:     _error.errorCode,
>> 	            userInfo: _error.errorUserInfo)
>> 	    }
>> 
>> 	    override var localizedDescription: String {
>> 	        return _error.errorDescription ?? super.localizedDescription
>> 	    }
>> 
>> 	    override var localizedFailureReason: String? {
>> 	        return _error.failureReason ?? super.localizedFailureReason
>> 	    }
>> 
>> 	    override var localizedRecoverySuggestion: String? {
>> 	        return _error.recoverySuggestion ?? super.localizedRecoverySuggestion
>> 	    }
>> 
>> 	    override var localizedRecoveryOptions: [String]? {
>> 	        return _error.recoveryOptions ?? super.localizedRecoveryOptions
>> 	    }
>> 
>> 	    override var recoveryAttempter: AnyObject? {
>> 	        if _error.recoveryOptions != nil {
>> 	            return _NSErrorRecoveryAttempter(error: _error)
>> 	        } else {
>> 	            return super.recoveryAttempter
>> 	        }
>> 	    }
>> 
>> 	    override var helpAnchor: String? {
>> 	        return _error.helpAnchor ?? super.helpAnchor
>> 	    }
>> 	}
> 
> We could, but why? This is precisely what user-info value providers were designed for.

If the NSError.setUserInfoValueProvider(forDomain:provider:) method isn't available in all supported target platforms, an NSError subclass seems to be the simpler option.

-- Ben



More information about the swift-evolution mailing list