> Le 5 août 2016 à 05:12, Kevin Ballard via swift-evolution > <swift-evolution@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 >>> <mailto:dgre...@apple.com>> wrote: >>> >>> >>>> On Aug 2, 2016, at 2:19 PM, Jon Shier <j...@jonshier.com >>>> <mailto: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 >>>>> <mailto:dgre...@apple.com>> wrote: >>>>> >>>>>> >>>>>> On Aug 2, 2016, at 10:30 AM, Jon Shier via swift-evolution >>>>>> <swift-evolution@swift.org <mailto:swift-evolution@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): >>>>> >>>>> 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 <mailto: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 <mailto: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 <mailto:swift-evolution@swift.org>> wrote: >>>>>>> > >>>>>>> > Proposal Link: >>>>>>> > https://github.com/apple/swift-evolution/blob/master/proposals/0112-nserror-bridging.md >>>>>>> > >>>>>>> > <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 <mailto:swift-evolution@swift.org> >>>>>>> > https://lists.swift.org/mailman/listinfo/swift-evolution >>>>>>> > <https://lists.swift.org/mailman/listinfo/swift-evolution> >>>>>>> >>>>>>> _______________________________________________ >>>>>>> swift-evolution mailing list >>>>>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>>>>>> _______________________________________________ >>>>>>> swift-evolution mailing list >>>>>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>>>>> >>>>>> >>>>>> _______________________________________________ >>>>>> swift-evolution mailing list >>>>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> <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