Swift不转换Objective-C NSError **抛出

我有一些Objective-C遗留代码,声明类似的方法

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

正如在这里写的https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/AdoptingCocoaDesignPatterns.html

Swift会自动将产生错误的Objective-C方法转换为根据Swift原生error handlingfunction抛出错误的方法。

但在我的项目中描述的方法是这样调用的:

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

而且,当我尝试使用它们时会抛出运行时exception:

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

我是否需要更多的东西来将Objective-C“NSError **”方法转换成Swift“trows”方法?

只有返回一个BOOL或一个(可空)对象的Objective-C方法被转换为Swift中的抛出方法。

原因是Cocoa方法总是使用返回值NOnil来指示方法的失败,而不仅仅是设置一个错误对象。 这在使用和创build错误对象 :

重要提示:成功或失败由方法的返回值指示。 尽pipe在Cocoa错误域中间接返回错误对象的Cocoa方法保证返回这样的对象,如果方法通过直接返回nil或NO来指示失败的话,你应该总是检查返回值是否为零,然后再尝试用NSError对象。

例如,Objective-C界面

 @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 

被映射为Swift

 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 } 

如果你可以改变你的方法的接口,那么你应该添加一个布尔返回值来表示成功或失败。

否则,你会从Swift中调用它

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

备注:

我发现Clang有一个强制函数在Swift中抛出错误的属性:

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

被映射为Swift

 public func doSomethingWithArgument5(x: Int32) throws 

并似乎“按预期”工作。 但是,我找不到关于这个属性的官方文档,所以依靠它可能不是一个好主意。

你需要让你的方法返回一个BOOL ,告诉运行时应该或不应该抛出一个错误。 另外,您应该将__autoreleasing添加到错误参数中,以确保ARC在您有机会使用它之前不会意外释放错误:

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

你可以像这样从Swift中调用它:

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