对于我的UIViewControllers ,我有一个非常简单的协议扩展,它具有通过轻击手势关闭键盘的功能。这是我的代码:
UIViewController
@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)
好的,我添加标签:
@objc func on(tap: UITapGestureRecognizer) { dismissKeyboard() }
但是,随后,它在此新添加的@objc标记上引发了不同的编译错误,并显示错误消息:
@objc只能与类的成员,@ objc协议和类的具体扩展一起使用
并建议通过 删除我刚刚被告知要添加的完全相同的标签 来“修复”它。
我本来以为@objc在协议定义之前添加即可解决任何#selector问题,但显然并非如此,这些周期性的错误消息/建议丝毫没有帮助。我对@objc在任何地方添加/删除标签optional,将方法标记为,在协议的定义中放置方法等一无所知。
#selector
optional
我在协议定义中输入的内容也没关系,保持扩展名不变,以下示例不起作用,协议定义中声明的方法的任何组合也不起作用:
@objc protocol KeyboardDismissing { func on(tap: UITapGestureRecognizer) }
这使我误以为它可以通过作为独立协议进行编译来工作,但是第二个尝试将其添加到视图控制器中:
class ViewController: UIViewController, KeyboardDismissing {}
它会吐出原始错误。
有人可以解释我做错了什么以及如何编译吗?
这是一个Swift协议扩展。无论如何,Objective-C都看不到Swift协议扩展。对他们一无所知。但是#selector关于Objective- C看到并调用您的函数。那不会发生,因为您的on(tap:)功能 仅 在协议扩展中定义。因此,编译器正确地阻止了您。
on(tap:)
这个问题是一大类问题,人们认为通过尝试通过协议将Objective-C调用的功能(选择器,委托方法等)注入到类中,人们认为他们在处理可可时将对协议扩展很聪明。延期。这是一个吸引人的概念,但它根本行不通。