Swift doesn't convert Objective-C NSError** to throws

I have some Objective-C legacy code, that declares method like

- (void)doSomethingWithArgument:(ArgType)argument error:(NSError **)error

As written here https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/AdoptingCocoaDesignPatterns.html

  • How can I handle donations through iOS?
  • Simplified screen capture: record video of only what appears within the layers of a UIView?
  • What the meaning of question mark '?' in swift?
  • Clang(LLVM) compile with frameworks
  • How do I intercept tapping of the done button in AVPlayerViewController?
  • Alamofire playground example breaks with HTTPS URL in version 1.2.1
  • Swift automatically translates Objective-C methods that produce errors
    into methods that throw an error according to Swift’s native error
    handling functionality.

    But in my project described methods are called like this:

    object.doSomething(argument: ArgType, error: NSErrorPointer)
    

    Moreover, it throws runtime exception when I try to use them like:

    let errorPtr = NSErrorPointer()
    object.doSomething(argumentValue, error: errorPtr)
    

    Do I need something more to convert Objective-C “NSError **” methods to Swift “trows” methods?

    2 Solutions Collect From Internet About “Swift doesn't convert Objective-C NSError** to throws”

    Only Objective-C methods which return a BOOL or a (nullable) object
    are translated to throwing methods in Swift.

    The reason is that Cocoa methods always use a return value NO or nil
    to indicate the failure of a method, and not just set an error object.
    This is documented in
    Using and Creating Error Objects:

    Important: Success or failure is indicated by the return value of the method.
    Although Cocoa methods that indirectly return error objects in the Cocoa error
    domain are guaranteed to return such objects if the method indicates failure
    by directly returning nil or NO, you should always check that the return
    value is nil or NO before attempting to do anything with the NSError object.

    For example, the Objective-C interface

    @interface OClass : NSObject
    
    NS_ASSUME_NONNULL_BEGIN
    
    -(void)doSomethingWithArgument1:(int) x error:(NSError **)error;
    -(BOOL)doSomethingWithArgument2:(int) x error:(NSError **)error;
    -(NSString *)doSomethingWithArgument3:(int) x error:(NSError **)error;
    -(NSString * _Nullable)doSomethingWithArgument4:(int) x error:(NSError **)error;
    
    NS_ASSUME_NONNULL_END
    
    @end
    

    is mapped to Swift as

    public class OClass : NSObject {
    
        public func doSomethingWithArgument1(x: Int32, error: NSErrorPointer)
        public func doSomethingWithArgument2(x: Int32) throws
        public func doSomethingWithArgument3(x: Int32, error: NSErrorPointer) -> String
        public func doSomethingWithArgument4(x: Int32) throws -> String
    }
    

    If you can change the interface of your method then you should add a boolean
    return value to indicate success or failure.

    Otherwise you would call it from Swift as

    var error : NSError?
    object.doSomethingWithArgument(argumentValue, error: &error)
    if let theError = error {
        print(theError)
    }
    

    Remark: At

    I found that Clang has an attribute which forces a function to throw an error in Swift:

    -(void)doSomethingWithArgument5:(int) x error:(NSError **)error
      __attribute__((swift_error(nonnull_error)));
    

    is mapped to Swift as

    public func doSomethingWithArgument5(x: Int32) throws
    

    and seems to work “as expected”. However, I could not find any official documentation
    about this attribute, so it might not be a good idea to rely on it.

    You need to make your method return a BOOL, to tell the runtime that an error should or should not be thrown. Also you should add __autoreleasing to the error parameter, to make sure ARC doesn’t accidentally release the error before you have a chance to use it:

    - (BOOL)doSomethingWithArgument:(ArgType)argument error:(NSError * __autoreleasing *)error
    

    You can then call it from Swift like this:

    do {
        object.doSomethingWithArgument(someArgument)
    } catch let err as NSError {
        print("Error: \(err)")
    }