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

使用选择器错误的Swift 3协议扩展

单于扬
2023-03-14
问题内容

对于我的UIViewControllers ,我有一个非常简单的协议扩展,它具有通过轻击手势关闭键盘的功能。这是我的代码:

@objc protocol KeyboardDismissing { 
    func on(tap: UITapGestureRecognizer)
}

extension KeyboardDismissing where Self: UIViewController {

    func addDismissalGesture() {
        let tap = UITapGestureRecognizer(target: self, action: #selector(Self.on(tap:)))
        view.addGestureRecognizer(tap)
    }

    func on(tap: UITapGestureRecognizer) {
        dismissKeyboard()
    }

    func dismissKeyboard() {
        view.endEditing(true)
    }
}

问题是上面的代码在此行上引发了编译错误:

let tap = UITapGestureRecognizer(target: self, action: #selector(Self.on(tap:)))

带有错误信息:

“ #selector”的参数引用实例方法“ on(tap :)”,而该方法未公开给Objective-C

并建议在“ @objc之前”添加“修复”func on(tap: UITapGestureRecognizer)

好的,我添加标签:

@objc func on(tap: UITapGestureRecognizer) {
    dismissKeyboard()
}

但是,随后,它在此新添加的@objc标记上引发了不同的编译错误,并显示错误消息:

@objc只能与类的成员,@ objc协议和类的具体扩展一起使用

并建议通过 删除我刚刚被告知要添加的完全相同的标签 来“修复”它。

我本来以为@objc在协议定义之前添加即可解决任何#selector问题,但显然并非如此,这些周期性的错误消息/建议丝毫没有帮助。我对@objc在任何地方添加/删除标签optional,将方法标记为,在协议的定义中放置方法等一无所知。

我在协议定义中输入的内容也没关系,保持扩展名不变,以下示例不起作用,协议定义中声明的方法的任何组合也不起作用:

@objc protocol KeyboardDismissing { 
    func on(tap: UITapGestureRecognizer)
}

这使我误以为它可以通过作为独立协议进行编译来工作,但是第二个尝试将其添加到视图控制器中:

class ViewController: UIViewController, KeyboardDismissing {}

它会吐出原始错误。

有人可以解释我做错了什么以及如何编译吗?


问题答案:

这是一个Swift协议扩展。无论如何,Objective-C都看不到Swift协议扩展。对他们一无所知。但是#selector关于Objective-
C看到并调用您的函数。那不会发生,因为您的on(tap:)功能 在协议扩展中定义。因此,编译器正确地阻止了您。

这个问题是一大类问题,人们认为通过尝试通过协议将Objective-C调用的功能(选择器,委托方法等)注入到类中,人们认为他们在处理可可时将对协议扩展很聪明。延期。这是一个吸引人的概念,但它根本行不通。



 类似资料:
  • 为什么这在《雨燕3》中行不通?它会在运行时崩溃,并表示: “-[MY_APP_NAME.DisplayOtherappSCTRL TAP:]:无法识别的选择器已发送到实例0x17ECEB70”

  • 问题内容: 我有一个协议扩展,它过去在swift 2.2之前可以完美地工作。 现在我有一个警告,告诉我使用新的,但是如果我添加它 没有使用Objective-C选择器声明任何方法。 我尝试通过以下几行代码重现该问题,可以轻松将其复制并粘贴到操场上 还有一个建议在协议中附加到该方法,但是如果我这样做,它还会要求我将其添加到实现该方法的类中,但是一旦添加,该类便不再符合该协议,因为它不符合该协议似乎看

  • 据我所知,协议缓冲区主要用于控制服务器和客户端代码的项目。我的一般问题是——协议缓冲区能否用于将二进制消息序列化/反序列化到使用现有协议的服务器?所以,我的问题: > 如果协议缓冲区不支持本机微调现有协议的序列化/反序列化方式,那么可以通过扩展添加该功能吗?是否可以以某种方式添加序列化/反序列化方法可以识别的关键字?也许这可以通过扩展或修改protobuf csharp port或protobuf

  • 问题内容: 我试图在所有符合协议的UIViewControllers中添加点按功能。 以下是我的做法: 点击屏幕时,结果如下: 我了解此错误,但不知道如何解决。谁能建议如何做到这一点? 问题答案: 问题在于,Objective-C不了解协议扩展。因此,您不能使用协议扩展将方法注入到类中,而Objective- C的消息传递机制可以看到该方法。您需要在视图控制器类 本身中 声明。 (我意识到这正是您

  • 问题内容: 我想知道在一个仅包含初始化功能并且仅打算在具体类中进行扩展的简单类中,对于等效于该初始值设定项的协议等效于什么。 因此,最简单的方法可能就是显示代码-我正在寻找与以下内容等效的协议扩展: 我期望代码看起来像这样: 我已经看到其他StackOverflow问题中建议的解决方案,但是我不确定它们是否有效,也不确定在类初始化程序中专门解决此问题。 问题答案: 您必须提供一个有效的初始化链来创

  • 扩展说明 RPC 协议扩展,封装远程调用细节。 契约: 当用户调用 refer() 所返回的 Invoker 对象的 invoke() 方法时,协议需相应执行同 URL 远端 export() 传入的 Invoker 对象的 invoke() 方法。 其中,refer() 返回的 Invoker 由协议实现,协议通常需要在此 Invoker 中发送远程请求,export() 传入的 Invoker