强制返回 `id` 和 inout NSError 的 Objective-C 方法桥接到可选返回
Posted
技术标签:
【中文标题】强制返回 `id` 和 inout NSError 的 Objective-C 方法桥接到可选返回【英文标题】:Force Objective-C method returning `id` and inout NSError to bridge to an optional return 【发布时间】:2018-09-18 21:48:54 【问题描述】:考虑这个 Objective-C 类:
@interface TestAPI : NSObject
-(nullable id)aNullableMethod;
-(nullable id)aNullableMethodWithError:(inout NSError **)error;
@end
我正在使用TestAPI
作为抽象基类,并希望在 Swift 中继承它。
Swift 将此代码桥接成如下所示(即对应菜单 -> Swift 4.2 界面):
open class TestAPI : NSObject
open func aNullableMethod() -> Any?
open func aNullableMethodWithError() throws -> Any
问题在于aNullableMethodWithError()
可以将nil
作为有效值返回。
如何让 Swift 相信 aNullableMethodWithError()
返回 Any?
而不是 Any
?
或者有没有更好的编写Objective-C方法签名的方法?
【问题讨论】:
返回nil
有什么意义,如果不是“发生错误,我无法返回任何有意义的东西”?
@matt - 我的示例故意简单地展示了我所看到的桥接问题。想象一个代表一个联系人的类,我想请求一个字段名称“BusinessPhoneNumber”。缺少业务电话号码不是错误,所以我想返回nil
。
但是在那个例子中,为什么会有一个采用NSError**
的方法呢?你明白我在说什么吗?你人为地提出了一个反模式,我要求你用实际的术语来证明这一点。只要你遵守模式就没有“桥接问题”,没有理由不这样做,那么为什么不直接遵守呢?
参见***.com/q/34786115/2976878 - 导入器假定返回nil
意味着该方法抛出了错误(这就是Cocoa 约定)。如果您真的想忽略该约定,则可以使用 __attribute__((swift_error(nonnull_error)))
如 Martin 的答案底部所示来更改行为,以便如果该方法在输出中留下非零 NSError*
时被认为已抛出 -参数(从而保留返回的可选性)。
【参考方案1】:
您可能需要使用NS_SWIFT_NOTHROW
:
-(nullable id)aNullableMethodWithError:(inout NSError **)error NS_SWIFT_NOTHROW;
这是导入到 Swift 中的:
open func aNullableMethodWithError(_ error: NSErrorPointer) -> Any?
如果您想将您的方法导入为throws
-function,您可能需要更改方法签名以遵循约定:
true
或非零(如果没有错误)
返回 false
或返回 nil 错误
类似这样的:
-(BOOL)aNullableMethod:(id*)object withError:(inout NSError **)error;
在斯威夫特中:
open func aNullableMethod(_ object: AutoreleasingUnsafeMutablePointer<AnyObject?>!) throws
【讨论】:
以上是关于强制返回 `id` 和 inout NSError 的 Objective-C 方法桥接到可选返回的主要内容,如果未能解决你的问题,请参考以下文章
无法使用类型为“(设备:AVCaptureDevice!,错误:inout NSError?)”的参数列表调用类型“AVCaptureDeviceInput”的初始化程序