If all you want to do is get the localized description, then you can just say `(error as NSError).localizedDescription`.
-Kevin On Fri, Aug 5, 2016, at 02:59 AM, Jean-Daniel Dupas wrote: > >> Le 5 août 2016 à 05:12, Kevin Ballard via swift-evolution <swift- >> evolut...@swift.org> a écrit : >> >> With NSError, you *must* check the domain before trying to interpret >> the code, or else your code is buggy and will behave incorrectly when >> receiving an unexpected error. > > You must check before interpreting the code, but you don’t have to > interpret the code to do something useful with an NSError. > > I think what Jon is looking for is ‘LocalizedError’ and > ‘CustomNSError’. > Is there any guarantee that casting an NSError into a CustomNSError or > LocalizedError will always succeed ? > >> With SE-0112, instead of checking the domain, you check if the Error >> can be casted to the particular error type that represents the >> domain. There is a one-to-one correspondence between domains and the >> new error types. For example, NSCocoaErrorDomain is represented by >> CocoaError, NSURLErrorDomain is URLError, etc. >> >> So previously you might have code that looks like >> >> func handleError(error: NSError) { >> switch error.domain { >> case NSCocoaErrorDomain where error.code == >> NSFileNoSuchFileError: >> let path = error.userInfo[NSFilePathErrorKey] as? String >> // handle error for path >> case NSURLErrorDomain where error.code == NSURLErrorTimedOut: >> let url = error.userInfo[NSURLErrorKey] as? NSURL >> // handle error for url >> default: >> // generic handling of other errors >> } >> } >> >> And now you'd write that like >> >> func handleError(error: Error) { >> switch error { >> case let error as CocoaError where error.code == >> .fileNoSuchFileError: >> let path = error.filePath >> // handle error for path >> case let error as URLError where error.code == .timedOut: >> let url = error.failingURL >> // handle error for url >> default: >> // generic handling of other errors >> } >> } >> >> It's the same basic structure, except now you get strong typing, you >> can't possibly forget to check the domain (which is a surprisingly >> common bug I see in a lot of code), and you get convenient accessors >> for the values stored in the user info. >> >> And if you don't actually care about any of the user info properties, >> then the new version is much simpler than the old: >> >> func handleError(error: Error) { >> switch error { >> case CocoaError.fileNoSuchFileError: >> // handle error >> case URLError.timedOut: >> // handle error >> default: >> // generic handling of other errors >> } >> } >> >> It's similar to checking the code without the domain in the old >> style, except now it checks the domain automatically, so you *still* >> can't accidentally interpret an error's code in the wrong domain. >> >> -Kevin Ballard >> >> On Thu, Aug 4, 2016, at 11:00 AM, Jon Shier via swift- >> evolution wrote: >>> Doug: >>> Thanks for indulging me so far, I think I’ve almost got it. Prior to >>> this, using NSError, I could just look at the relevant properties of >>> the error if I needed to see what type it was. Network errors had >>> different codes from CloudKit errors, POSIX errors were underlying >>> FileManager errors. A bit complex due to the undocumented nature of >>> so many of these errors, but I could ignore any aspect of the error >>> I didn’t care about. Now, however, it seems I must always care about >>> what types of errors come out of various methods, as I’ll need to >>> cast to the appropriate types to get useful information. For >>> example, how would you handle the CloudKit errors I mentioned >>> before? It seems to me like I would need to, at the point where I >>> need to extract useful information, do a switch on various casts. >>> First, try casting to CKError, then to CocoaError (?), and then >>> likely produce a fatalError if there’s an unexpected type. Or is >>> Error guaranteed to always cast to something useful? I’ve read the >>> proposal a few times now and it looks like a lot of casting is going >>> to be required, I’m mostly curious about the recommended patterns, >>> especially for asynchronous calls that don’t go through throw/catch. >>> >>> >>> >>> Jon >>> >>> >>>> On Aug 2, 2016, at 5:36 PM, Douglas Gregor <dgre...@apple.com> >>>> wrote: >>>> >>>> >>>>> On Aug 2, 2016, at 2:19 PM, Jon Shier <j...@jonshier.com> wrote: >>>>> >>>>> Thanks Doug. I missed the rename, as earlier points still referred >>>>> to ErrorProtocol. In regards to the CloudKit errors, I appreciate >>>>> the strongly typed CKError, but why not have the methods return >>>>> that type directly? >>>> >>>> Generally speaking, Cocoa only uses NSError—not specific subclasses >>>> or NSError or other error types—because errors can occur at many >>>> different places in the stack and be propagated up. A CloudKit >>>> operation could fail because of some problem detected in a >>>> different error domain—say, the general Cocoa error domain or >>>> URLError domain—and that non-CloudKit error would get passed >>>> through immediately. So, if you were assuming that every error you >>>> get here had to be in the CloudKit error domain, I believe your >>>> code was already incorrect. It is *possible* that CloudKit >>>> translates/wraps all other errors, but that would be odd for a >>>> Cocoa framework. >>>> >>>>> Every usage of these methods is going to require such a cast, so >>>>> why require it in the first place? I don’t understand what >>>>> advantage erasing the strongly type error that was just created >>>>> has when the developer will just have to bring it right back. Or >>>>> is this just a first implementation? >>>> >>>> There was never a strongly-typed error, and in most Cocoa cases >>>> there shouldn’t be one because NSError covers all error domains, by >>>> design. >>>> >>>> - Doug >>>> >>>> >>>>> >>>>> >>>>> Jon >>>>> >>>>>> On Aug 2, 2016, at 4:20 PM, Douglas Gregor <dgre...@apple.com> >>>>>> wrote: >>>>>> >>>>>>> >>>>>>> On Aug 2, 2016, at 10:30 AM, Jon Shier via swift-evolution <swift- >>>>>>> evolut...@swift.org> wrote: >>>>>>> >>>>>>> I’m not sure where to put such feedback, but the ErrorProtocol >>>>>>> to Error rename that accompanied the implementation of this >>>>>>> proposal is very, very painful. It completely eliminates the >>>>>>> very useful ability to embed an associated Error type inside >>>>>>> other types, as those types now conflict with the protocol. >>>>>>> Also, was this rename accompanied by an evolution proposal? It >>>>>>> seems like the change was just made when this proposal was >>>>>>> implemented. >>>>>> >>>>>> The rename was part of the proposal, in bullet #5 of the proposed >>>>>> solution (which, amusing, pastes as bullet #1 below): >>>>>> >>>>>> 1. Rename ErrorProtocol to Error: once we've completed the >>>>>> bridging story, Error becomes the primary way to work with >>>>>> error types in Swift, and the value type to which NSError is >>>>>> bridged: >>>>>> func handleError(_ error: Error, userInteractionPermitted: Bool) >>>>>> >>>>>> >>>>>>> Also, the adoption of this proposal by the Cocoa(Touch) >>>>>>> frameworks as seen in Xcode 8 beta 4 has made asynchronous error >>>>>>> handling quite a bit more arduous. For example, the CKDatabase >>>>>>> method fetch(withRecordID recordID: CKRecordID, >>>>>>> completionHandler: (CKRecord?, Error?) -> Void) returns an >>>>>>> `Error` now, meaning I have to cast to the specific `CKError` >>>>>>> type to get useful information out of it. Is this just an >>>>>>> unfortunate first effort that will be fixed, or is this the >>>>>>> expected form of these sorts of APIs after this proposal? >>>>>> >>>>>> Prior to this proposal, you would have had to check the domain >>>>>> against CKErrorDomain anyway to determine whether you’re looking >>>>>> at a CloudKit error (vs. some other error that is passing through >>>>>> CloudKit), so error bridging shouldn’t actually be adding any >>>>>> work here—although it might be making explicit work that was >>>>>> already done or should have been done. Once you have casted to >>>>>> CKError, you now have typed accessors for information in the >>>>>> error: >>>>>> >>>>>> extension CKError { >>>>>> /// Retrieve partial error results associated by item ID. >>>>>> public var partialErrorsByItemID: [NSObject : Error]? { >>>>>> return userInfo[CKPartialErrorsByItemIDKey] as? [NSObject : >>>>>> Error] >>>>>> } >>>>>> >>>>>> /// The original CKRecord object that you used as the basis for >>>>>> /// making your changes. >>>>>> public var ancestorRecord: CKRecord? { >>>>>> return userInfo[CKRecordChangedErrorAncestorRecordKey] as? >>>>>> CKRecord >>>>>> } >>>>>> >>>>>> /// The CKRecord object that was found on the server. Use this >>>>>> /// record as the basis for merging your changes. >>>>>> public var serverRecord: CKRecord? { >>>>>> return userInfo[CKRecordChangedErrorServerRecordKey] as? >>>>>> CKRecord >>>>>> } >>>>>> >>>>>> /// The CKRecord object that you tried to save. This record is >>>>>> based >>>>>> /// on the record in the CKRecordChangedErrorAncestorRecordKey >>>>>> key >>>>>> /// but contains the additional changes you made. >>>>>> public var clientRecord: CKRecord? { >>>>>> return userInfo[CKRecordChangedErrorClientRecordKey] as? >>>>>> CKRecord >>>>>> } >>>>>> >>>>>> /// The number of seconds after which you may retry a request. >>>>>> This >>>>>> /// key may be included in an error of type >>>>>> /// `CKErrorServiceUnavailable` or `CKErrorRequestRateLimited`. >>>>>> public var retryAfterSeconds: Double? { >>>>>> return userInfo[CKErrorRetryAfterKey] as? Double >>>>>> } >>>>>> } >>>>>> - Doug >>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> Jon Shier >>>>>>> >>>>>>> >>>>>>>> On Jul 12, 2016, at 8:44 AM, Shawn Erickson via swift-evolution >>>>>>>> <swift-evolution@swift.org> wrote: >>>>>>>> >>>>>>>> Thanks for the effort on the proposal and discussion and thanks >>>>>>>> to those working in the implementation. >>>>>>>> >>>>>>>> -Shawn >>>>>>>> On Tue, Jul 12, 2016 at 12:25 AM Charles Srstka via swift- >>>>>>>> evolution <swift-evolution@swift.org> wrote: >>>>>>>>> Wow, thanks! I’m delighted that Apple found this improvement >>>>>>>>> to be worth inclusion in Swift 3. This will truly make the >>>>>>>>> language much nicer to use with the Cocoa frameworks. >>>>>>>>> >>>>>>>>> Thanks! >>>>>>>>> >>>>>>>>> Charles >>>>>>>>> >>>>>>>>> > On Jul 11, 2016, at 11:19 PM, Chris Lattner via swift- >>>>>>>>> > evolution <swift-evolution@swift.org> wrote: >>>>>>>>> > >>>>>>>>> > Proposal Link: >>>>>>>>> > https://github.com/apple/swift-evolution/blob/master/proposals/0112-nserror-bridging.md >>>>>>>>> > >>>>>>>>> > The review of "SE-0112: Improved NSError Bridging" ran from >>>>>>>>> > June 30 ... July 4, 2016. The proposal has been *accepted*: >>>>>>>>> > >>>>>>>>> > The community and core team agree that this proposal is a >>>>>>>>> > huge step forward that enriches the experience working with >>>>>>>>> > and extending the Cocoa NSError model in Swift. The core >>>>>>>>> > team requests one minor renaming of >>>>>>>>> > "attemptRecovery(optionIndex:andThen:)" to >>>>>>>>> > "attemptRecovery(optionIndex:resultHandler:)”. It also >>>>>>>>> > discussed renaming CustomNSError and RecoverableError, but >>>>>>>>> > decided to stay with those names. >>>>>>>>> > >>>>>>>>> > Thank you to Doug Gregor and Charles Srstka for driving this >>>>>>>>> > discussion forward, and for Doug Gregor taking the charge on >>>>>>>>> > the implementation effort to make this happen for Swift 3! >>>>>>>>> > >>>>>>>>> > -Chris Lattner >>>>>>>>> > Review Manager >>>>>>>>> > >>>>>>>>> > _______________________________________________ >>>>>>>>> > swift-evolution mailing list >>>>>>>>> > swift-evolution@swift.org >>>>>>>>> > https://lists.swift.org/mailman/listinfo/swift-evolution >>>>>>>>> >>>>>>>>> _______________________________________________ >>>>>>>>> swift-evolution mailing list >>>>>>>>> swift-evolution@swift.org >>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>>>>>> _______________________________________________ >>>>>>>> swift-evolution mailing list >>>>>>>> swift-evolution@swift.org >>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>>>>> >>>>>>> _______________________________________________ >>>>>>> swift-evolution mailing list >>>>>>> swift-evolution@swift.org >>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> _________________________________________________ >>> swift-evolution mailing list >>> swift-evolution@swift.org >>> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution