我正在try 将我的项目源代码从Swift 3转换为Swift 4.Xcode给我的一个警告是关于我的 Select 器.

例如,我使用常规 Select 器将目标添加到按钮,如下所示:

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

这是它显示的警告:

"#selector"的参数引用了"ViewController"中的实例方法"myAction()",该方法依赖于Swift 4中不推荐使用的"@objc"属性推断

添加"@objc"以向Objective-C公开此实例方法

现在,在错误消息上点击Fix会对我的函数产生以下影响:

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

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

我真的不想把我所有的函数都重命名为包含@objc标记,我想这是没有必要的.

如何重写 Select 器以处理弃用?


Related question:

推荐答案

修正是正确的——为了使它所指的方法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,考虑到上面提到的成员不必要地接触的缺点.

Swift相关问答推荐

输出NSView到png

";async let和";async之间的差异让我们等待";

更改正在进行的异步任务的完成(SWIFT并发)(&q;)?

音频播放器无法播放URL音频(操作系统状态错误2003334207.)

如何在设备(或常量)地址空间中创建缓冲区?

SwiftUI 交易:根据外部状态制作一个动画或静止的按钮

在领域 SwiftUI 异常中使用 Apple 登录:无法识别的 Select 器发送到实例

我如何读取并通知可可 macos 中某个类的计算(computed)属性?

如何删除 macOS 中的所有命令?

SwiftUI - Select 器没有 Select 值

将内容与工作表顶部而不是中间对齐

如何获得不同的插入和移除过渡动画?

Swift:withCheckedContinuation 和 Dispatch QoSClass

阻止其他类型的键盘

Swift - 如何更新多目录中的对象

如果没有标记,则为 Swift 预处理器

如何从一个可观察的数组创建一个可观察的数组?

Swift - 迭代 struct 对象时如何对其进行变异

在 Swift 中覆盖 UIScrollView 的委托属性(就像 UICollectionView 一样)

WKWebView 确实从本地文档文件夹加载资源