Objective-c 代码的 Swift 3 闭包语法

Posted

技术标签:

【中文标题】Objective-c 代码的 Swift 3 闭包语法【英文标题】:Swift 3 closure syntax for objective-c code 【发布时间】:2016-09-23 17:40:57 【问题描述】:

我正在使用一个公开以下 Objective-c 方法的库:

- (void)signIn:(NSString *)username  password:(NSString *)password completion:(void (^)(User *user, NSError *error))completion;

我想像这样调用 swift 3 中的方法:

sign(in: "abc",  password: "def")  (user: User?, error: NSError?) -> Void in
    // ...

编译器引发以下错误:

无法将类型 '(User?, NSError?) -> Void' 的值转换为预期的参数类型 '((User?, Error?) -> Void)!'

在这个例子中我遗漏了什么?

【问题讨论】:

【参考方案1】:

当您在 Xcode 中查看库的标题时,点击“相关项目”弹出菜单(编辑器左上方的四个正方形图标)并选择“生成的界面”。这将向您展示您的 ObjC 代码的 Swift 接口是什么样的,包括该闭包参数的类型签名。

很可能类似于@escaping (user: User?, error: Error?) -> Void。但这只是我的猜测——请务必阅读生成的界面。

注意:

导入的闭包假定为@escaping。 (不过,当您创建要传递给您的函数的闭包时,您不必在使用站点上编写它。) NSError 指针通常被转换为Error 协议引用。 参数类型是作为可选还是非可选导入取决于 ObjC 文件中的可空性(或 NS_ASSUME_NONNULL)注释。

【讨论】:

感谢生成界面的提示。不幸的是,它仍然没有解决问题。这是输出:open func log(in username: String!, password: String!, completion: (@escaping (User?, Error?) -> Swift.Void)!) 【参考方案2】:

Xcode 的自动完成功能可以为您提供很多帮助。从弹出菜单中选择函数,按 Tab 以获取函数签名,再按几个 Tab 直到到达 completion 参数,然后按 Enter。这是 XCode 给我的:

instance.sign(in: String!, password: String!)  (User?, Error?) in
    // code

所以你的闭包语法应该是这样的:

instance.sign(in: String!, password: String!)  user, error in
    // code

【讨论】:

以上是关于Objective-c 代码的 Swift 3 闭包语法的主要内容,如果未能解决你的问题,请参考以下文章

Swift 3.0 令人兴奋,但Objective-C也有小改进--Objective-C的类属性

转换为 Swift 3 重命名了我自己的 Objective-C 方法

Swift 3 获取请求错误(警告:无法加载任何 Objective-C 类信息)

在 Swift 中使用 Objective-C 枚举

在objective-c中使用swift代码时的问题

Swift 代码是不是在底层变成了优化的 Objective-C 代码?