> Le 5 août 2016 à 05:12, Kevin Ballard via swift-evolution
> <[email protected]> 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 <[email protected]
>>> <mailto:[email protected]>> wrote:
>>>
>>>
>>>> On Aug 2, 2016, at 2:19 PM, Jon Shier <[email protected]
>>>> <mailto:[email protected]>> 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 <[email protected]
>>>>> <mailto:[email protected]>> wrote:
>>>>>
>>>>>>
>>>>>> On Aug 2, 2016, at 10:30 AM, Jon Shier via swift-evolution
>>>>>> <[email protected] <mailto:[email protected]>> 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
>>>>>>> <[email protected] <mailto:[email protected]>> 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
>>>>>>> <[email protected] <mailto:[email protected]>> 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
>>>>>>> > <[email protected] <mailto:[email protected]>> 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
>>>>>>> > [email protected] <mailto:[email protected]>
>>>>>>> > https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>> > <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> swift-evolution mailing list
>>>>>>> [email protected] <mailto:[email protected]>
>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>>> _______________________________________________
>>>>>>> swift-evolution mailing list
>>>>>>> [email protected] <mailto:[email protected]>
>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>>>
>>>>>>
>>>>>> _______________________________________________
>>>>>> swift-evolution mailing list
>>>>>> [email protected] <mailto:[email protected]>
>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution