Swift 不会将 Objective-C NSError** 转换为抛出
Swift doesn't convert Objective-C NSError** to throws
我有一些 Objective-C 遗留代码,它声明了类似
的方法
- (void)doSomethingWithArgument:(ArgType)argument error:(NSError **)error
Swift automatically translates Objective-C methods that produce errors
into methods that throw an error according to Swift’s native error
handling functionality.
但是在我的项目中描述的方法是这样调用的:
object.doSomething(argument: ArgType, error: NSErrorPointer)
此外,当我尝试像这样使用它们时它会抛出运行时异常:
let errorPtr = NSErrorPointer()
object.doSomething(argumentValue, error: errorPtr)
我需要更多的东西来将 Objective-C "NSError **" 方法转换为 Swift "trows" 方法吗?
您需要将方法 return 设为 BOOL
,以告知运行时应该或不应该抛出错误。您还应该将 __autoreleasing
添加到错误参数,以确保 ARC 在您有机会使用它之前不会意外释放错误:
- (BOOL)doSomethingWithArgument:(ArgType)argument error:(NSError * __autoreleasing *)error
然后您可以从 Swift 调用它,如下所示:
do {
object.doSomethingWithArgument(someArgument)
} catch let err as NSError {
print("Error: \(err)")
}
只有Objective-C
方法被翻译成抛出Swift
方法,它做return一个BOOL
(不是lower-casedbool
),或 nullable-object。
(使用 Xcode 11.7 和 Swift 5 语言测试。)
原因是 Cocoa 方法总是使用 return 值 NO
或 nil
来指示方法的失败,而 not 只是设置一个错误对象。
这记录在
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.
例如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;
-(BOOL)doSomething:(NSError **)error;
NS_ASSUME_NONNULL_END
@end
映射到 Swift 为
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
}
如果您可以更改方法的接口,那么您应该添加一个布尔值
return 表示成功或失败的值。
否则你会把它从 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
并且似乎“按预期”工作。但是,我找不到任何官方文档
关于这个属性,所以依赖它可能不是一个好主意。
我有一些 Objective-C 遗留代码,它声明了类似
的方法- (void)doSomethingWithArgument:(ArgType)argument error:(NSError **)error
Swift automatically translates Objective-C methods that produce errors into methods that throw an error according to Swift’s native error handling functionality.
但是在我的项目中描述的方法是这样调用的:
object.doSomething(argument: ArgType, error: NSErrorPointer)
此外,当我尝试像这样使用它们时它会抛出运行时异常:
let errorPtr = NSErrorPointer()
object.doSomething(argumentValue, error: errorPtr)
我需要更多的东西来将 Objective-C "NSError **" 方法转换为 Swift "trows" 方法吗?
您需要将方法 return 设为 BOOL
,以告知运行时应该或不应该抛出错误。您还应该将 __autoreleasing
添加到错误参数,以确保 ARC 在您有机会使用它之前不会意外释放错误:
- (BOOL)doSomethingWithArgument:(ArgType)argument error:(NSError * __autoreleasing *)error
然后您可以从 Swift 调用它,如下所示:
do {
object.doSomethingWithArgument(someArgument)
} catch let err as NSError {
print("Error: \(err)")
}
只有Objective-C
方法被翻译成抛出Swift
方法,它做return一个BOOL
(不是lower-casedbool
),或 nullable-object。
(使用 Xcode 11.7 和 Swift 5 语言测试。)
原因是 Cocoa 方法总是使用 return 值 NO
或 nil
来指示方法的失败,而 not 只是设置一个错误对象。
这记录在
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.
例如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;
-(BOOL)doSomething:(NSError **)error;
NS_ASSUME_NONNULL_END
@end
映射到 Swift 为
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
}
如果您可以更改方法的接口,那么您应该添加一个布尔值 return 表示成功或失败的值。
否则你会把它从 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
并且似乎“按预期”工作。但是,我找不到任何官方文档 关于这个属性,所以依赖它可能不是一个好主意。