【发布时间】:2017-03-10 19:52:28
【问题描述】:
我有一个我认为是我的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' 的参数指的是没有暴露给 Objective-C 的实例方法 'on(tap:)'
建议通过在func on(tap: UITapGestureRecognizer) 之前添加@objc 来“修复它”
好的,我添加标签:
@objc func on(tap: UITapGestureRecognizer) {
dismissKeyboard()
}
但是,它会在这个新添加的@objc 标记上引发不同的编译错误,并带有错误消息:
@objc 只能与类的成员、@objc 协议和类的具体扩展一起使用
建议通过删除与我刚刚被告知要添加的完全相同的标签来“修复它”。
我原本以为在我的协议定义之前添加@objc 可以解决任何#selector 问题,但显然情况并非如此,而且这些周期性错误消息/建议丝毫没有帮助。我在到处添加/删除@objc 标签、将方法标记为optional、将方法放入协议的定义等方面进行了疯狂的追逐。
我在协议定义中放什么也无关紧要保持扩展不变,以下示例不起作用,协议定义中声明的方法的任何组合也不起作用:
@objc protocol KeyboardDismissing {
func on(tap: UITapGestureRecognizer)
}
这让我误以为它是通过编译为独立协议来工作的,但第二次我尝试将它添加到视图控制器:
class ViewController: UIViewController, KeyboardDismissing {}
它吐回原来的错误。
谁能解释我做错了什么以及如何编译它?
注意:
我查看了this question,但它适用于 Swift 2.2 而不是 Swift 3,也不会在您创建一个继承自示例中定义的协议的视图控制器类后立即编译答案。
我也看过this question,但答案使用NotificationCenter,这不是我想要的。
如果还有其他看似重复的问题,请告诉我。
【问题讨论】:
-
好眼光,我尝试合并该答案无济于事。我应该指出,这是针对 Swift 3 而不是 Swift Swift3 标签来反映这一点。
-
谁投了反对票,你能解释一下吗?如果我知道问题出在哪里,我会编辑我的问题以改进它。
-
投反对票的原因是这是明显的重复,如果不是这个,那么许多其他问题已经以同样的方式得到了回答。您正在尝试通过协议扩展将 Objective-C 可调用功能(选择器、委托方法等)注入到类中。那是行不通的。
-
很遗憾,但它“就是这样”。 Swift 很棒,但它仍然是一门语言。
标签: ios objective-c swift swift3 protocols