swift - 如何在 Swift 4 中使用 #selector() 处理 @objc 推理弃用?

标签 swift xcode swift4

我正在尝试将项目的源代码从 Swift 3 转换为 Swift 4。Xcode 给我的一个警告是关于我的选择器的。

例如,我使用这样的常规选择器将目标添加到按钮:

button.addTarget(self, action: #selector(self.myAction), for: .touchUpInside)

这是它显示的警告:

Argument of '#selector' refers to instance method 'myAction()' in 'ViewController' that depends on '@objc' attribute inference deprecated in Swift 4

Add '@objc' to expose this instance method to Objective-C

现在,点击错误消息上的 Fix 对我的函数执行此操作:

// before
func myAction() { /* ... */ }

// after
@objc func myAction() { /* ... */ }

我真的不想重命名我的所有函数以包含 @objc 标记,我认为这没有必要。

如何重写选择器以处理弃用问题?


相关问题:

最佳答案

修复是正确的——您无法更改选择器以使其引用的方法暴露给 Objective-C。

首先发出此警告的全部原因是 SE-0160 的结果.在 Swift 4 之前,internal 或更高版本的 NSObject 继承类的 Objective-C 兼容成员被推断为 @objc,因此暴露给 Objective- C,因此允许使用选择器调用它们(因为需要 Obj-C 运行时才能查找给定选择器的方法实现)。

但是在 Swift 4 中,情况不再如此。现在只有非常具体的声明被推断为 @objc,例如,@objc 方法的重写,@objc 协议(protocol)要求和声明的实现具有暗示 @objc 的属性,例如 @IBOutlet

这背后的动机,详情 in the above linked proposal ,首先是为了防止 NSObject 继承类中的方法重载由于具有相同的选择器而相互冲突。其次,它不必为不需要暴露给 Obj-C 的成员生成 thunk,从而有助于减小二进制文件的大小,第三,它提高了动态链接的速度。

如果要将某个成员暴露给Obj-C,需要将其标记为@objc,例如:

class ViewController: UIViewController {

    @IBOutlet weak var button: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
        button.addTarget(self, action: #selector(foo), for: .touchUpInside)
    }

    <b>@objc</b> func foo() {
       // ... 
    }
}

(在选择了“最小化推理”选项的情况下运行时,迁移器应该使用选择器自动为您执行此操作)

要向 Obj-C 公开一组成员,您可以使用 @objc 扩展名:

@objc extension ViewController {

    // both exposed to Obj-C
    func foo() {}
    func bar() {}
}

这会将其中定义的所有成员暴露给 Obj-C,并对任何不能暴露给 Obj-C 的成员给出错误(除非明确标记为 @nonobjc)。

如果您有一个类,您需要将所有 Obj-C 兼容成员暴露给 Obj-C,您可以将该类标记为 @objcMembers:

@objcMembers
class ViewController: UIViewController {
   // ...
}

现在,所有可以推断为@objc 的成员都将是。但是,我不建议这样做,除非您真的需要所有成员都暴露给 Obj-C,考虑到上述让成员不必要地暴露的缺点。

关于swift - 如何在 Swift 4 中使用 #selector() 处理 @objc 推理弃用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46374082/

相关文章:

ios - Xcode 9 - 无法为应用程序包 ID 创建 IXPlaceholder

arrays - Swift:在可选上使用 .sorted 时,对成员 '+' 的引用不明确

swift - 在 Swift 中获取构建日期和时间

swift - 是否有将应用程序重置为初始阶段的功能?

ios - 如何根据消息的长度更改 messageCell 的宽度?在 swift 4

objective-c - 使用 Swift 4 在 Xcode 9 上找不到“ProjectName-Swift.h”文件?

json - 如何在 Swift [45] 可解码协议(protocol)中解码 JSON 字典类型的属性

ios - 发出多个异步请求,但仅等待一个

ios - 无法在模拟器 "The operation couldn’ 上运行应用程序无法完成。 (LaunchServicesError 错误 0。)”

xcode - 将弹出框选择到静态单元格UITableView会导致编译错误