我试图在所有符合协议的UIViewControllers中添加点按功能MyProtocol。
MyProtocol
以下是我的做法:
import UIKit protocol MyProtocol: class{ var foo: String? {get set} func bar() } extension MyProtocol where Self: UIViewController { func bar() { print(foo) } } class TestViewController: UIViewController, MyProtocol{ var foo: String? override func viewDidLoad() { super.viewDidLoad() foo = "testing" let tapGesture = UITapGestureRecognizer(target: self, action: "bar") }
点击屏幕时,结果如下:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: unrecognized selector sent to instance
我了解此错误,但不知道如何解决。谁能建议如何做到这一点?
问题在于,Objective-C不了解协议扩展。因此,您不能使用协议扩展将方法注入到类中,而Objective- C的消息传递机制可以看到该方法。您需要bar在视图控制器类 本身中 声明。
bar
(我意识到这正是您要避免这样做的方法,但是我无能为力。)
一种解决方法可能是这样的:
override func viewDidLoad() { super.viewDidLoad() foo = "testing" let tapGesture = UITapGestureRecognizer(target: self, action: "baz") self.view.addGestureRecognizer(tapGesture) } func baz() { self.bar() }
现在,我们使用Objective- C的消息传递机制进行调用baz,然后使用Swift的消息传递机制进行调用bar,这当然是有效的。我意识到它并不像您想的那样干净,但是至少现在实现bar可以在协议扩展中使用。
baz
(当然,另一种解决方案是做在协议扩展存在之前我们所做的事情:使所有视图控制器都从包含的一些通用自定义UIViewController子类继承bar。)