修正是正确的——为了使它所指的方法expose 于Objective-C,你不能更改 Select 器的任何内容.
这一警告的全部原因首先是SE-0160次调查的结果.在Swift 4之前,NSObject
个继承类的internal
个或更高的Objective-C兼容成员被推断为@objc
个,因此expose 于Objective-C,因此允许使用 Select 器调用它们(因为需要Obj-C运行时来查找给定 Select 器的方法实现).
然而,在Swift 4中,情况不再如此.现在,只有非常具体的声明被推断为@objc
,例如,@objc
个方法的重写、@objc
个协议需求的实现,以及具有暗示@objc
的属性的声明,例如@IBOutlet
.
如第in the above linked proposal条所述,这背后的动机首先是防止NSObject
个继承类中的方法重载由于具有相同的 Select 器而相互冲突.第二,它不必为不需要expose 于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() {
// ...
}
}
(the migrator should do this automatically for you with selectors when running with the "minimise inference" option selected)
要向Obj-C公开一组成员,可以使用@objc extension
:
@objc extension ViewController {
// both exposed to Obj-C
func foo() {}
func bar() {}
}
这将向Obj-C公开其中定义的所有成员,并在无法向Obj-C公开的任何成员上给出一个错误(除非明确标记为@nonobjc
).
如果您有一个需要all个Obj-C兼容成员才能expose 于Obj-C的类,则可以将该类标记为@objcMembers
:
@objcMembers
class ViewController: UIViewController {
// ...
}
现在,所有可以推断为@objc
的成员都将被删除.然而,我不建议这样做,除非你really需要所有成员接触Obj-C,考虑到上面提到的成员不必要地接触的缺点.