Swift调用Objective-C返回BOOL的方法时返回值被推断为()而非Bool
问题原因
该报错由Swift对Objective-C方法的默认桥接规则导致:
- 按照Cocoa通用约定,返回BOOL且最后一个参数为
NSError **类型的Objective-C方法,Swift会默认将其转换为throws类型的无返回值方法:原方法返回YES时Swift判定执行成功,不抛出错误;原方法返回NO时Swift自动将errorPtr指向的NSError对象抛出,原BOOL返回值会被直接丢弃。因此你调用方法得到的ret类型为Void(也就是()),无法作为Bool类型用于条件判断。 - 你提到的返回值在
dispatch_sync内部赋值是方法的实现逻辑,和本次报错没有关联。
解决方案
根据你是否可以修改原Objective-C方法代码,有两种可选方案:
方案1:可修改原OC方法代码
在方法声明末尾添加NS_SWIFT_NOTHROW注解,主动告知Swift不要将该方法转换为throws方法,保留原BOOL返回值:
- (BOOL)methodName:(NSDictionary<NSString *, NSString *> *)params callback:(void(^)(NSString *_Nullable, ErrorInformation *_Nullable))callback error:(NSError *_Nullable *_Nullable)errorPtr NS_SWIFT_NOTHROW;
修改后Swift中调用该方法的返回值为Bool类型,error参数变为UnsafeMutablePointer<NSError?>?类型,可自行处理error指针,也能正常判断返回值:
var error: NSError? let ret = methodName(params, callback: { result, infoError in // 处理回调逻辑 }, error: &error) if ret { // 原返回值为YES的逻辑 }
方案2:无法修改原OC方法代码
如果不需要额外判断BOOL返回值,可以直接使用默认的do/try/catch逻辑:原方法返回YES时try语句不会抛出错误,直接执行do块内的逻辑即可,不需要额外接收返回值判断:
do { try methodName(params, callback: { result, infoError in // 处理回调逻辑 }) // 走到此处等价于原OC方法返回YES,直接写原if(ret)内的逻辑即可 } catch { // 原方法返回NO的逻辑,error为原errorPtr指向的NSError对象 }
如果既不能修改OC代码又要拿到BOOL返回值,可以在Objective-C层新增一个分类方法,包装原方法并添加NS_SWIFT_NOTHROW注解,再在Swift中调用新的包装方法即可。
注意:上述示例中调用方法时需要传入完整的params和callback参数,你提供的示例中
methodName()仅为简写。
内容的提问来源于stack exchange,提问作者Ben Butterworth
相关产品推荐
相关产品推荐

