在Swift 4中,如何使用#selector()处理@objc推理弃用?
我正在尝试将项目的源代码从Swift 3转换为Swift4。Xcode给我的一个警告是关于选择器的信息。
例如,我使用常规选择器将目标添加到按钮,如下所示:
button.addTarget(self, action: #selector(self.myAction), for: .touchUpInside)
这是显示的警告:
“ #selector”的参数引用“ ViewController”中的实例方法“ myAction()”,该方法依赖于Swift 4中弃用的“ @objc”属性推断
添加“ @objc”以将该实例方法公开给Objective-C
现在,点击Fix
错误消息会对我的功能执行此操作:
// beforefunc 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
协议要求的实现以及带有暗示属性的声明@objc
,例如@IBOutlet
。
如上面链接的提案中所述,其背后的动机是,首先是为了防止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)
}
**@objc** func foo() {
// ...
}
}
(在选择了“最小推理”选项的情况下,迁移程序应使用选择器自动为您执行此操作)
要将一组成员暴露给Obj-C,可以使用@objc extension
:
@objc extension ViewController { // both exposed to Obj-C
func foo() {}
func bar() {}
}
这会将其中定义的所有成员公开给Obj-C,并为所有无法公开给Obj-C的成员提供错误(除非明确标记为@nonobjc
)。
如果您有一个班级,需要让 所有与 Obj-C兼容的成员都可以使用Obj-C,则可以将该班级标记为@objcMembers
:
@objcMembersclass ViewController: UIViewController {
// ...
}
现在,可以推断为所有成员@objc
。但是,我不建议这样做,除非您 确实 需要所有成员都与Obj-C接触,因为上面提到的不必要地暴露成员的缺点。
以上是 在Swift 4中,如何使用#selector()处理@objc推理弃用? 的全部内容, 来源链接: utcz.com/qa/429165.html