<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><blockquote type="cite" class="">On Jun 30, 2016, at 5:36 PM, Charles Srstka via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""></blockquote><div><blockquote type="cite" class=""><br class="Apple-interchange-newline"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><blockquote type="cite" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div class=""><span class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">One comment though:</span><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">Why is the errorDescription of LocalizedError an optional? Why would a type conform to this protocol, and then choose not to provide its only extension to ErrorProtocol?</span></div></blockquote></div><br class=""><div class="">This one’s my fault; Gregory originally had this as a non-optional and I recommended changing it, because Cocoa uses a nil value for NSLocalizedDescriptionKey to indicate that the default behavior should be used to construct the error string. In my experience, this is usually in fact what you want, and NSLocalizedFailureReasonErrorKey is a better fit for most purposes. For example, when throwing an error in an NSDocument subclass:</div><div class=""><br class=""></div><div class=""><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">override</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">func</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> read(from data: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(112, 61, 170);">Data</span><span class="" style="font-variant-ligatures: no-common-ligatures;">, ofType typeName: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(112, 61, 170);">String</span><span class="" style="font-variant-ligatures: no-common-ligatures;">) </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">throws</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> {</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);"><span class="" style="font-variant-ligatures: no-common-ligatures;"> </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">let</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> userInfo = [</span><span class="" style="font-variant-ligatures: no-common-ligatures;">NSLocalizedFailureReasonErrorKey</span><span class="" style="font-variant-ligatures: no-common-ligatures;">: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);">"Something went wrong."</span><span class="" style="font-variant-ligatures: no-common-ligatures;">]</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;"> </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">throw</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(112, 61, 170);">NSError</span><span class="" style="font-variant-ligatures: no-common-ligatures;">(domain: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);">"Foo"</span><span class="" style="font-variant-ligatures: no-common-ligatures;">, code: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(39, 42, 216);">1</span><span class="" style="font-variant-ligatures: no-common-ligatures;">, userInfo: userInfo)</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;">}</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;"><br class=""></span></div><div class="" style="margin: 0px; line-height: normal;">In the example above, the error is presented to the user as “The operation could not be completed. Something went wrong.”</div><div class="" style="margin: 0px; line-height: normal;"><br class=""></div><div class="" style="margin: 0px; line-height: normal;">However, if you fill in the localized description instead of the failure reason, like this:</div><div class="" style="margin: 0px; line-height: normal;"><br class=""></div><div class="" style="margin: 0px; line-height: normal;"><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">override</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">func</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> read(from data: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(112, 61, 170);">Data</span><span class="" style="font-variant-ligatures: no-common-ligatures;">, ofType typeName: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(112, 61, 170);">String</span><span class="" style="font-variant-ligatures: no-common-ligatures;">) </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">throws</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> {</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);"><span class="" style="font-variant-ligatures: no-common-ligatures;"> </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">let</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> userInfo = [</span><span class="" style="font-variant-ligatures: no-common-ligatures;">NSLocalizedDescriptionKey</span><span class="" style="font-variant-ligatures: no-common-ligatures;">: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);">"Something went wrong."</span><span class="" style="font-variant-ligatures: no-common-ligatures;">]</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;"> </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">throw</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(112, 61, 170);">NSError</span><span class="" style="font-variant-ligatures: no-common-ligatures;">(domain: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);">"Foo"</span><span class="" style="font-variant-ligatures: no-common-ligatures;">, code: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(39, 42, 216);">1</span><span class="" style="font-variant-ligatures: no-common-ligatures;">, userInfo: userInfo)</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;">}</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;"><br class=""></span></div><div class="" style="margin: 0px; line-height: normal;"><span class="" style="font-variant-ligatures: no-common-ligatures;">The user is shown “The operation could not be completed.” with no further information.</span></div><div class="" style="margin: 0px; line-height: normal;"><span class="" style="font-variant-ligatures: no-common-ligatures;"><br class=""></span></div><div class="" style="margin: 0px; line-height: normal;">Even when you’re reporting errors directly, the behavior is different whether you provide the localized description or omit it. With a nil description, as below:</div><div class="" style="margin: 0px; line-height: normal;"><br class=""></div><div class="" style="margin: 0px; line-height: normal;"><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">let</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> userInfo = [NSLocalizedFailureReasonErrorKey: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);">"Something went wrong."</span><span class="" style="font-variant-ligatures: no-common-ligatures;">]</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;">NSApp.presentError(NSError(domain: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);">"Foo"</span><span class="" style="font-variant-ligatures: no-common-ligatures;">, code: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(39, 42, 216);">1</span><span class="" style="font-variant-ligatures: no-common-ligatures;">, userInfo: userInfo))</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;"><span class="" style="font-family: Helvetica; font-size: 12px;"><br class=""></span></div><div class="" style="margin: 0px; line-height: normal; min-height: 13px;"><span class="" style="font-variant-ligatures: no-common-ligatures;"></span>The error is presented as “The operation could not be completed. Something went wrong.” By comparison, if we provide the description:</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;"><span class="" style="font-variant-ligatures: no-common-ligatures;"></span><br class=""></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">let</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> userInfo = [NSLocalizedDescriptionKey: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);">"Something went wrong."</span><span class="" style="font-variant-ligatures: no-common-ligatures;">]</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;">NSApp.presentError(NSError(domain: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);">"Foo"</span><span class="" style="font-variant-ligatures: no-common-ligatures;">, code: </span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(39, 42, 216);">1</span><span class="" style="font-variant-ligatures: no-common-ligatures;">, userInfo: userInfo))</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures;"><br class=""></span></div><div class="" style="margin: 0px; line-height: normal;">The error is simply reported as “Something went wrong.” This seems somewhat brusque, compared to the more polite and blow-softening behavior of the former example.</div><div class="" style="margin: 0px; line-height: normal;"><br class=""></div><div class="" style="margin: 0px; line-height: normal;">Unfortunately, I can’t think of any way for this property to return a non-optional, human-readable string to the end user while still communicating to NSError that the field should be nil, unless the default implementation can either copy the code that NSError uses to generate this value, or call through to NSError to generate it. I do notice that NSError always returns something appropriate when you call -localizedDescription on it, although it has the advantage that that method is only used to retrieve the value, not to provide it, unlike here.</div></div></div></div></div></div></blockquote></div><br class=""><div class="">Actually, looking at the proposal again, it looks like Gregory has already solved this issue. #4 under Proposed Solution mentions a “localizedDescription” property on Error/ErrorProperty, provided by Foundation, which appears to do the equivalent of calling -localizedDescription on NSError. The optional “errorDescription” property on CustomCocoaError/CustomNSError is there for bridging purposes, and localizedDescription is what you’d use to get the string for presentation. Having separate APIs for separate purposes is probably better than trying to hack two uses into the same property, honestly.</div><div class=""><br class=""></div><div class="">Charles</div><div class=""><br class=""></div></body></html>