Swift doesn't convert Objective-C NSError** to throws
Only Objective-C
methods are translated to throwing Swift
methods, which do return a BOOL
(not lower-cased bool
), or a nullable-object.(Tested with Xcode 11.7, and Swift 5 language.)
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 inUsing 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 errordomain are guaranteed to return such objects if the method indicates failureby directly returning nil or NO, you should always check that the returnvalue is nil or NO before attempting to do anything with the NSError object.
For example, the Objective-C interface
@interface OClass : NSObjectNS_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;-(BOOL)doSomething:(NSError **)error;NS_ASSUME_NONNULL_END@end
is mapped to Swift as
open class OClass : NSObject { open func doSomethingWithArgument1(x: Int32, error: NSErrorPointer) open func doSomethingWithArgument2(x: Int32) throws open func doSomethingWithArgument3(x: Int32, error: NSErrorPointer) -> String open func doSomethingWithArgument4(x: Int32) throws -> String open func doSomething() throws}
If you can change the interface of your method then you should add a booleanreturn 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 documentationabout 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)")}