当前位置: 首页 > 面试题库 >

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

纪枫
2023-03-14
问题内容

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

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

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标记,并且我认为这不是必需的。

如何重写选择器以应对弃用?


问题答案:

修复程序是正确的-选择器没有任何改变,您可以更改以使其所引用的方法公开给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

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

现在,可以推断为所有成员@objc。但是,我不建议这样做,除非您 确实 需要所有成员都与Obj-C接触,因为上面提到的不必要地暴露成员的缺点。



 类似资料:
  • 我试图让我的头周围的promise,我得到了这个错误抱怨未处理的promise拒绝,但我确实有一个<代码>捕捉如果它被拒绝! 谁能帮帮我我做错了什么? 这是我的代码: 错误: (节点:200092)未处理的PromisejectionWarning:未处理的promise拒绝。这个错误要么是由于在没有catch块的情况下抛出异步函数的内部,要么是因为拒绝了没有使用catch块处理的promise。

  • 我正在尝试安装JTransforms库。我已经下载了。来自此处的jar文件:https://sites.google.com/site/piotrwendykier/software/jtransforms 我下载的是具有依赖关系的二进制文件:JTransforms-3.1-with-dependentials。罐子 我将名称改为jtransforms。jar并将文件复制到libraries/jt

  • 我遵循这个链接的第二个答案(两个步骤)来实现视频到Youtube的上传:使用curl和api v3在Youtube上上传视频 代码工作正常,但当我执行时,我得到的响应是:状态:嵌入:true license:“YouTube”privacystatus:“unlisted”publicstatsviewable:true uploadstatus:“uploaded”

  • 代码错误 行,我在控制台中得到如下错误:无法找到元素:{“method”:“id”,“selector”:“loginusername”}命令持续时间或超时:262毫秒

  • 其中是我的服务实现类。 在部署机器上,我将kubeconfig文件放在~/.kube/config上,并且命令行很好。 我不知道如何处理这个问题。知道我该如何找出异常的原因吗? 提前谢谢!

  • 问题内容: 我正在连接到一个网站,正在登录。 该网站将我重定向到新页面,并且Mechanize处理所有cookie和重定向作业,但是,我找不到最后一页。我使用Firebug并再次完成了相同的工作,然后发现我必须通过Mechanize传递另外两页。 我快速浏览了一下页面,发现有一些JavaScript和HTML代码,但由于它看起来不像普通的页面代码而无法理解。这些页面是做什么用的?他们如何重定向到其