> On Jun 29, 2016, at 5:30 PM, Paul Cantrell via swift-evolution 
> <[email protected]> wrote:
> 
>> On Jun 27, 2016, at 1:17 PM, Douglas Gregor via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> 
>> The LocalizedError protocol describes an error that provides localized 
>> messages for display to the end user, all of which provide default 
>> implementations. The conforming type can provide implementations for any 
>> subset of these requirements:
>> 
>> protocol LocalizedError : Error {
>>   /// A localized message describing what error occurred.
>>   var errorDescription: String? { get }
>>   …
>> }
> 
> 
> Given that LocalizedError would now be its own protocol that not all errors 
> would conform to, could errorDescription be non-optional?
> 
>>   var errorDescription: String { get }
> 
> It would be nice if conformance to LocalizedError guaranteed the presence of 
> a user-readable message. Such a guarantee is useful when building a UI.
> 
> I realize the bridging to NSError may make this impossible, but in principle 
> it seems like the right design.

The trouble is that NSError allows NSLocalizedDescriptionKey to be nil, and 
leaving it nil is how you get Cocoa's default behavior in a lot of situations. 
In fact, this is usually what you want—leaving NSLocalizedDescriptionKey nil 
and populating NSLocalizedFailureReasonErrorKey instead is often the better way 
to go. For example, in NSDocument’s error reporting, if you throw an error that 
sets a failure reason, like this:

override func read(from data: Data, ofType typeName: String) throws {
    let userInfo = [NSLocalizedFailureReasonErrorKey: "Something went wrong."]
    throw NSError(domain: "Foo", code: 1, userInfo: userInfo)
}

The error is presented to the user as “The operation could not be completed. 
Something went wrong.”

However, if you provide the description instead:

override func read(from data: Data, ofType typeName: String) throws {
    let userInfo = [NSLocalizedDescriptionKey: "Something went wrong."]
    throw NSError(domain: "Foo", code: 1, userInfo: userInfo)
}

You just get “The operation could not be completed.” with no further 
information.

Providing the failure reason while leaving the description nil also changes the 
presentation when you’re reporting errors directly, as below:

let userInfo = [NSLocalizedFailureReasonErrorKey: "Something went wrong."]
NSApp.presentError(NSError(domain: "Foo", code: 1, userInfo: userInfo))

This gives you “The operation could not be completed. Something went wrong.” By 
comparison:

let userInfo = [NSLocalizedDescriptionKey: "Something went wrong."]
NSApp.presentError(NSError(domain: "Foo", code: 1, userInfo: userInfo))

This just gives you “Something went wrong.” without the polite “The operation 
could not be completed.” prefix, which causes the error description to come 
across as rather blunt. A default implementation for the property could be 
provided, of course, but since the primary purpose of the methods in this 
protocol are for the implementer of the error type to provide information to 
the frameworks to assist in creating the NSError, I can’t think of any way to 
have it simultaneously return a meaningful value to a client and still 
communicate to the frameworks that this value should be nil.

Perhaps we should add an additional property for a user-facing string generated 
from the rest of the strings?

Charles

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to