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: public enum MyError: CustomNSError, Equatable { case one([String : Any]) case two([String : Any]) case three([String : Any]) /// The domain of the error. public static var errorDomain: String { return “MyError" } /// The error code within the given domain. public var errorCode: Int { switch self { case .one: return 50000 case .two: return 50001 case .three: return 50002 } } /// The user-info dictionary. public var errorUserInfo: [String : Any] { var userInfo = [String: Any]() if case let .one(info) = self { userInfo = info } else if case let .two(info) = self { userInfo = info } else if case let .three(info) = self { userInfo = info } return userInfo } } Thanks Ronak > On Sep 29, 2016, at 5:46 PM, Ronak via swift-users <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>> 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: >> >> extern NSString *const MyErrorDomain NS_REFINED_FOR_SWIFT; >> extern NSString *const MyErrorUserInfoStringKey NS_REFINED_FOR_SWIFT; >> >> typedef NS_ENUM(NSInteger, MyErrorCode) { >> MyErrorCodeOne, >> MyErrorCodeTwo, >> MyErrorCodeThree, >> } NS_REFINED_FOR_SWIFT; >> >> enum MyError: CustomNSError { >> >> case one(String) >> case two >> case three >> >> static var errorDomain: String { >> return __MyErrorDomain >> } >> >> var errorCode: Int { >> switch self { >> case .one: >> return __MyErrorCode.one.rawValue >> case .two: >> return __MyErrorCode.two.rawValue >> case .three: >> return __MyErrorCode.three.rawValue >> } >> } >> >> var errorUserInfo: [String: Any] { >> var userInfo = [String: Any]() >> if case let .one(string) = self { >> userInfo[__MyErrorUserInfoStringKey] = string >> } >> return userInfo >> } >> >> } >> >>> On Sep 29, 2016, at 1:17 PM, Ronak via swift-users <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 >>> @objc public class FoundationError: NSObject, CustomNSError { >>> >>> /// The underlying error code >>> private let code: FoundationError.Code >>> >>> /// The type of an error code. >>> @objc public enum Code: Int { >>> >>> /// An ARCOperationCondition failed during evaluation >>> case operationConditionFailed = 10000 >>> >>> /// An ARCOperation failed during execution >>> case operationExecutionFailed = 10001 >>> } >>> >>> /// The domain of the error. >>> public static var errorDomain: String { >>> return "FoundationError" >>> } >>> >>> /// The error code within the given domain. >>> public var errorCode: Int { >>> return code.rawValue >>> } >>> >>> /// The user-info dictionary. >>> public let errorUserInfo: [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 >>> public convenience init(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 >>> public init(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 >>> public override func isEqual(_ object: Any?) -> Bool { >>> guard let object = object as? FoundationError else { return false } >>> >>> return errorCode == 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 <mailto:swift-users@swift.org> >>> https://lists.swift.org/mailman/listinfo/swift-users >>> <https://lists.swift.org/mailman/listinfo/swift-users> >> > > _______________________________________________ > swift-users mailing list > swift-users@swift.org > https://lists.swift.org/mailman/listinfo/swift-users
_______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users