<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>