> 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

Reply via email to