<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 <<a href="mailto:ole@oleb.net" class="">ole@oleb.net</a>> 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="">   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="">   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 -> Objective-C.<br class=""><br class="">Here’s my implementation:<br class=""><br class="">publicenumMyError: CustomNSError, Equatable{<br class=""><br class=""> caseone([String: Any])<br class=""><br class=""> casetwo([String: Any])<br class=""><br class=""> casethree([String: Any])<br class=""><br class=""> /// The domain of the error.<br class=""> publicstaticvarerrorDomain: String{<br class="">   return“MyError"<br class=""> }<br class=""><br class=""> /// The error code within the given domain.<br class=""> publicvarerrorCode: Int{<br class="">   switchself{<br class="">   case.one:<br class="">     return50000<br class="">   case.two:<br class="">     return50001<br class="">   case.three:<br class="">     return50002<br class="">   }<br class=""> }<br class=""><br class=""> /// The user-info dictionary.<br class=""> publicvarerrorUserInfo: [String: Any] {<br class="">   varuserInfo = [String: Any]()<br class="">   ifcaselet.one(info) = self{<br class="">     userInfo = info<br class="">   } elseifcaselet.two(info) = self{<br class="">     userInfo = info<br class="">   } elseifcaselet.three(info) = self{<br class="">     userInfo = info<br class="">   }<br class=""><br class="">   returnuserInfo<br class=""> }<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=""><<a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a><span class="Apple-converted-space"> </span><<a href="mailto:swift-users@swift.org" class="">mailto:swift-users@swift.org</a>>> 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 <<a href="mailto:zach@waldowski.me" class="">zach@waldowski.me</a><br class=""><<a href="mailto:zach@waldowski.me" class="">mailto:zach@waldowski.me</a>>> 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="">   MyErrorCodeOne,<br class="">   MyErrorCodeTwo,<br class="">   MyErrorCodeThree,<br class="">} NS_REFINED_FOR_SWIFT;<br class=""><br class="">enumMyError: CustomNSError{<br class=""><br class="">   caseone(String)<br class="">   casetwo<br class="">   casethree<br class=""><br class="">   staticvarerrorDomain: String{<br class="">       return__MyErrorDomain<br class="">   }<br class=""><br class="">   varerrorCode: Int{<br class="">       switchself{<br class="">       case.one:<br class="">           return__MyErrorCode.one.rawValue<br class="">       case.two:<br class="">           return__MyErrorCode.two.rawValue<br class="">       case.three:<br class="">           return__MyErrorCode.three.rawValue<br class="">       }<br class="">   }<br class=""><br class="">   varerrorUserInfo: [String: Any] {<br class="">       varuserInfo = [String: Any]()<br class="">       ifcaselet.one(string) = self{<br class="">           userInfo[__MyErrorUserInfoStringKey] = string<br class="">       }<br class="">       returnuserInfo<br class="">   }<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=""><<a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a><span class="Apple-converted-space"> </span><<a href="mailto:swift-users@swift.org" class="">mailto:swift-users@swift.org</a>>> 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"> </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"> </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="">   /// The underlying error code<br class="">   privateletcode: FoundationError.Code<br class=""><br class="">   /// The type of an error code.<br class="">   @objcpublicenumCode: Int{<br class=""><br class="">       /// An ARCOperationCondition failed during evaluation<br class="">       caseoperationConditionFailed = 10000<br class=""><br class="">       /// An ARCOperation failed during execution<br class="">       caseoperationExecutionFailed = 10001<br class="">   }<br class=""><br class="">   /// The domain of the error.<br class="">   publicstaticvarerrorDomain: String{<br class="">       return"FoundationError"<br class="">   }<br class=""><br class="">   /// The error code within the given domain.<br class="">   publicvarerrorCode: Int{<br class="">       returncode.rawValue<br class="">   }<br class=""><br class="">   /// The user-info dictionary.<br class="">   publicleterrorUserInfo: [String: Any]<br class=""><br class="">   /// Initializes a new FoundationError with an empty userInfo<br class="">dictionary<br class="">   ///<br class="">   /// - parameter code: one of the available error codes<br class="">   ///<br class="">   /// - returns: a new instance of FoundationError<br class="">   publicconvenienceinit(code: FoundationError.Code) {<br class="">       self.init(code: code, userInfo: [:])<br class="">   }<br class=""><br class="">   /// Initializes a new FoundationError with an userInfo dictionary<br class="">   ///<br class="">   /// - parameter code: one of the available error codes<br class="">   /// - parameter userInfo: the user-info dictionary<br class="">   ///<br class="">   /// - returns: a new instance of FoundationError<br class="">   publicinit(code: FoundationError.Code, userInfo: [String: Any]) {<br class="">       self.code = code<br class="">       errorUserInfo = userInfo<br class="">   }<br class=""><br class="">   /// Computes whether two FoundationErrors are equal<br class="">   ///<br class="">   /// - parameter object: a FoundationError<br class="">   ///<br class="">   /// - returns: true, if the two errors are equal<br class="">   publicoverridefuncisEqual(_object: Any?) -> Bool{<br class="">       guardletobject = object as? FoundationErrorelse{ returnfalse}<br class=""><br class="">       returnerrorCode == object.errorCode &&<br class="">errorUserInfo.keys.elementsEqual(object.errorUserInfo.keys)<br class="">   }<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>