<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="">Hi Ole,<div class=""><br class=""></div><div class="">Yes that’s what I’m resorting to now. I had to change my Swift code to return NSError to all clients, regardless of language.</div><div class=""><br class=""></div><div class="">Therefore, I really wonder why CustomNSError even exists. I could have just used NSError from the get go...</div><div class=""><br class=""></div><div class="">Ronak</div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Mar 5, 2017, at 2:20 PM, Ole Begemann &lt;<a href="mailto:ole@oleb.net" class="">ole@oleb.net</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><span 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;" class="">Have you tried explicitly casting the value to NSError when you pass it to Objective-C? I think it should work then.</span><br 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;" class=""><br 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;" class=""><span 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;" class="">&nbsp;&nbsp;&nbsp;let myError: MyError = ...</span><br 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;" class=""><span 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;" class="">&nbsp;&nbsp;&nbsp;myObjCFunc(myError as NSError)</span><br 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;" class=""><br 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;" class=""><span 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;" class="">On 02/03/2017 17:29, Ronak via swift-users wrote:</span><br 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;" class=""><blockquote type="cite" 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;" class="">Hi everyone,<br class=""><br class="">It looks like I’m still having issues exposing a CustomNSError to<br class="">Objective-C. I am generating errors of this type in Swift and then<br class="">trying to bridge them in one direction over to Objective-C.<br class="">From Objective-C, this Error type is being exposed as a _SwiftValue.<br class=""><br class="">Do I have to mark this error as @objc and switch to using a raw enum? If<br class="">so, I fail to see the benefit of using CustomNSError or any of the new<br class="">error related protocols from Swift -&gt; Objective-C.<br class=""><br class="">Here’s my implementation:<br class=""><br class="">publicenumMyError: CustomNSError, Equatable{<br class=""><br class="">&nbsp;caseone([String: Any])<br class=""><br class="">&nbsp;casetwo([String: Any])<br class=""><br class="">&nbsp;casethree([String: Any])<br class=""><br class="">&nbsp;/// The domain of the error.<br class="">&nbsp;publicstaticvarerrorDomain: String{<br class="">&nbsp;&nbsp;&nbsp;return“MyError"<br class="">&nbsp;}<br class=""><br class="">&nbsp;/// The error code within the given domain.<br class="">&nbsp;publicvarerrorCode: Int{<br class="">&nbsp;&nbsp;&nbsp;switchself{<br class="">&nbsp;&nbsp;&nbsp;case.one:<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return50000<br class="">&nbsp;&nbsp;&nbsp;case.two:<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return50001<br class="">&nbsp;&nbsp;&nbsp;case.three:<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return50002<br class="">&nbsp;&nbsp;&nbsp;}<br class="">&nbsp;}<br class=""><br class="">&nbsp;/// The user-info dictionary.<br class="">&nbsp;publicvarerrorUserInfo: [String: Any] {<br class="">&nbsp;&nbsp;&nbsp;varuserInfo = [String: Any]()<br class="">&nbsp;&nbsp;&nbsp;ifcaselet.one(info) = self{<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;userInfo = info<br class="">&nbsp;&nbsp;&nbsp;} elseifcaselet.two(info) = self{<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;userInfo = info<br class="">&nbsp;&nbsp;&nbsp;} elseifcaselet.three(info) = self{<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;userInfo = info<br class="">&nbsp;&nbsp;&nbsp;}<br class=""><br class="">&nbsp;&nbsp;&nbsp;returnuserInfo<br class="">&nbsp;}<br class="">}<br class=""><br class="">Thanks<br class=""><br class="">Ronak<br class=""><br class=""><blockquote type="cite" class="">On Sep 29, 2016, at 5:46 PM, Ronak via swift-users<br class="">&lt;<a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a><span class="Apple-converted-space">&nbsp;</span>&lt;<a href="mailto:swift-users@swift.org" class="">mailto:swift-users@swift.org</a>&gt;&gt; wrote:<br class=""><br class="">Ahh..thanks for the reply Zach. I didn’t actually see your reply until<br class="">now.<br class=""><br class="">I’ll see how I can adjust my code.<br class=""><br class="">Thanks for this!<br class=""><br class=""><br class=""><blockquote type="cite" class="">On Sep 29, 2016, at 4:38 PM, Zach Waldowski &lt;<a href="mailto:zach@waldowski.me" class="">zach@waldowski.me</a><br class="">&lt;<a href="mailto:zach@waldowski.me" class="">mailto:zach@waldowski.me</a>&gt;&gt; wrote:<br class=""><br class="">Error types themselves shouldn’t generally cross into Objective-C,<br class="">because you don’t get interop; for that, we have Error, which crosses<br class="">the bridge as NSError.<br class=""><br class="">If it’s instructive to think of it this way, both Objective-C and<br class="">Swift should define errors in their best native way, and use NSError.<br class="">That’s, at least, the use case for CustomNSError and LocalizedError.<br class=""><br class="">If you’re primarily exporting errors from Objective-C to be “seen” in<br class="">Swift, you want to look into the ns_error_domain attribute on the C<br class="">side. This generates a good deal of the enum Code: Int boilerplate<br class="">coming in to Swift, but it’s obnoxious to create those errors from Swift.<br class=""><br class="">If you’re primarily exporting errors from Swift to Objective-C, you<br class="">can make any Swift type implement Error and CustomNSError, which can<br class="">then cross the bridge.<br class=""><br class="">The happy path of full error interop in both directions is a little<br class="">more complicated. Generally you have to start with one of the above<br class="">approach and “mirror” some values in the other language. Consider the<br class="">following as a slightly over-wrought example of having your cake and<br class="">eating it too:<br class=""><br class="">externNSString*constMyErrorDomain NS_REFINED_FOR_SWIFT;<br class="">externNSString*constMyErrorUserInfoStringKey NS_REFINED_FOR_SWIFT;<br class=""><br class="">typedefNS_ENUM(NSInteger, MyErrorCode) {<br class="">&nbsp;&nbsp;&nbsp;MyErrorCodeOne,<br class="">&nbsp;&nbsp;&nbsp;MyErrorCodeTwo,<br class="">&nbsp;&nbsp;&nbsp;MyErrorCodeThree,<br class="">} NS_REFINED_FOR_SWIFT;<br class=""><br class="">enumMyError: CustomNSError{<br class=""><br class="">&nbsp;&nbsp;&nbsp;caseone(String)<br class="">&nbsp;&nbsp;&nbsp;casetwo<br class="">&nbsp;&nbsp;&nbsp;casethree<br class=""><br class="">&nbsp;&nbsp;&nbsp;staticvarerrorDomain: String{<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return__MyErrorDomain<br class="">&nbsp;&nbsp;&nbsp;}<br class=""><br class="">&nbsp;&nbsp;&nbsp;varerrorCode: Int{<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switchself{<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case.one:<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return__MyErrorCode.one.rawValue<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case.two:<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return__MyErrorCode.two.rawValue<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case.three:<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return__MyErrorCode.three.rawValue<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br class="">&nbsp;&nbsp;&nbsp;}<br class=""><br class="">&nbsp;&nbsp;&nbsp;varerrorUserInfo: [String: Any] {<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;varuserInfo = [String: Any]()<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ifcaselet.one(string) = self{<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;userInfo[__MyErrorUserInfoStringKey] = string<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;returnuserInfo<br class="">&nbsp;&nbsp;&nbsp;}<br class=""><br class="">}<br class=""><br class=""><blockquote type="cite" class="">On Sep 29, 2016, at 1:17 PM, Ronak via swift-users<br class="">&lt;<a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a><span class="Apple-converted-space">&nbsp;</span>&lt;<a href="mailto:swift-users@swift.org" class="">mailto:swift-users@swift.org</a>&gt;&gt; wrote:<br class=""><br class="">Hello all,<br class=""><br class="">We are proceeding to update all of our Swift code to Swift 3 now and<br class="">had a few questions about the proper way to implement Errors. We<br class="">need these entities to be available in Objective-C and they are<br class="">actively being used in Swift classes marked as @objc.<br class=""><br class="">I<br class="">read:<span class="Apple-converted-space">&nbsp;</span><a href="https://github.com/apple/swift-evolution/blob/master/proposals/0112-nserror-bridging.md" class="">https://github.com/apple/swift-evolution/blob/master/proposals/0112-nserror-bridging.md</a><span class="Apple-converted-space">&nbsp;</span>completely<br class="">and came up with this implementation:<br class=""><br class=""><br class="">/// The enumeration of the possible error codes in the Foundation<br class="">error domain<br class="">@objcpublicclassFoundationError: NSObject, CustomNSError{<br class=""><br class="">&nbsp;&nbsp;&nbsp;/// The underlying error code<br class="">&nbsp;&nbsp;&nbsp;privateletcode: FoundationError.Code<br class=""><br class="">&nbsp;&nbsp;&nbsp;/// The type of an error code.<br class="">&nbsp;&nbsp;&nbsp;@objcpublicenumCode: Int{<br class=""><br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// An ARCOperationCondition failed during evaluation<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;caseoperationConditionFailed = 10000<br class=""><br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// An ARCOperation failed during execution<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;caseoperationExecutionFailed = 10001<br class="">&nbsp;&nbsp;&nbsp;}<br class=""><br class="">&nbsp;&nbsp;&nbsp;/// The domain of the error.<br class="">&nbsp;&nbsp;&nbsp;publicstaticvarerrorDomain: String{<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return"FoundationError"<br class="">&nbsp;&nbsp;&nbsp;}<br class=""><br class="">&nbsp;&nbsp;&nbsp;/// The error code within the given domain.<br class="">&nbsp;&nbsp;&nbsp;publicvarerrorCode: Int{<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;returncode.rawValue<br class="">&nbsp;&nbsp;&nbsp;}<br class=""><br class="">&nbsp;&nbsp;&nbsp;/// The user-info dictionary.<br class="">&nbsp;&nbsp;&nbsp;publicleterrorUserInfo: [String: Any]<br class=""><br class="">&nbsp;&nbsp;&nbsp;/// Initializes a new FoundationError with an empty userInfo<br class="">dictionary<br class="">&nbsp;&nbsp;&nbsp;///<br class="">&nbsp;&nbsp;&nbsp;/// - parameter code: one of the available error codes<br class="">&nbsp;&nbsp;&nbsp;///<br class="">&nbsp;&nbsp;&nbsp;/// - returns: a new instance of FoundationError<br class="">&nbsp;&nbsp;&nbsp;publicconvenienceinit(code: FoundationError.Code) {<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.init(code: code, userInfo: [:])<br class="">&nbsp;&nbsp;&nbsp;}<br class=""><br class="">&nbsp;&nbsp;&nbsp;/// Initializes a new FoundationError with an userInfo dictionary<br class="">&nbsp;&nbsp;&nbsp;///<br class="">&nbsp;&nbsp;&nbsp;/// - parameter code: one of the available error codes<br class="">&nbsp;&nbsp;&nbsp;/// - parameter userInfo: the user-info dictionary<br class="">&nbsp;&nbsp;&nbsp;///<br class="">&nbsp;&nbsp;&nbsp;/// - returns: a new instance of FoundationError<br class="">&nbsp;&nbsp;&nbsp;publicinit(code: FoundationError.Code, userInfo: [String: Any]) {<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.code = code<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;errorUserInfo = userInfo<br class="">&nbsp;&nbsp;&nbsp;}<br class=""><br class="">&nbsp;&nbsp;&nbsp;/// Computes whether two FoundationErrors are equal<br class="">&nbsp;&nbsp;&nbsp;///<br class="">&nbsp;&nbsp;&nbsp;/// - parameter object: a FoundationError<br class="">&nbsp;&nbsp;&nbsp;///<br class="">&nbsp;&nbsp;&nbsp;/// - returns: true, if the two errors are equal<br class="">&nbsp;&nbsp;&nbsp;publicoverridefuncisEqual(_object: Any?) -&gt; Bool{<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;guardletobject = object as? FoundationErrorelse{ returnfalse}<br class=""><br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;returnerrorCode == object.errorCode &amp;&amp;<br class="">errorUserInfo.keys.elementsEqual(object.errorUserInfo.keys)<br class="">&nbsp;&nbsp;&nbsp;}<br class="">}<br class=""><br class="">My question is whether this is the correct way to do this now; or is<br class="">there another solution we should be doing? We would like to follow<br class="">Swift Best Practices here, but unfortunately, the documentation is<br class="">quite vague on this subject.<br class=""><br class=""><br class="">Thanks for your help!<br class=""><br class="">Ronak Patel</blockquote></blockquote></blockquote></blockquote></div></blockquote></div><br class=""></div></body></html>