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