协议中的默认实现不适合我的情况

时间:2017-04-28 10:50:25

标签: ios swift

我在这个例子中模拟了我的情况:

protocol MyProtocol {

    func doSomething()
}

extension MyProtocol {

    func doSomething() {
        print("Do something")
    }
}

class MyViewController: UIViewController, MyProtocol {

    let button = UIButton()

    override func viewDidLoad() {
        super.viewDidLoad()
        button.addTarget(self, action: #selector(doSomething), for: .touchUpInside)
    }
}

我原以为MyViewController已经实施了doSomething()功能,因为它是在MyProtocol扩展名中实现的。不幸的是我收到了这个错误:

  

错误:' #selector'的参数指实例方法   ' doSomething的()'没有暴露于Objective-C

我可以修复或解决此问题吗?

2 个答案:

答案 0 :(得分:0)

您的协议与Objective-C不兼容。您需要使用@objc对其进行注释,否则您将无法使用选择器,因为这些方法不会使用Objective-C调度。

修改

所以我应该在之前在的操场上尝试过它。

您无法在Swift中向协议扩展添加@objc函数。你必须把它放在课堂上。或者你可以扩展UIViewController来实现MyProtocol

e.g。

@objc protocol MyProtocol 
{
    @objc func doSomething();
} 

extension UIViewController: MyProtocol
{
    @objc func doSomething() { /* implementation */ }   
}

答案 1 :(得分:0)

我遇到了同样的问题并用包装对象解决了它。

protocol MyProtocol: class {

    func doSomething()
}

extension MyProtocol {

    func doSomething() {
        print("Do something")
    }
}

final class ObjCMyProtocolWrap: NSObject, MyProtocol {

    // MARK: - init

    override init() {
        fatalError("Not supported!")
    }

    init(_ origin: MyProtocol) {
        self.origin = origin
    }

    // MARK: - protocol: Executable

    func doSomething() {
        origin.doSomething()
    }

    // MARK: - private

    private let origin: MyProtocol

}

现在你可以像这样使用它:

let action: MyProtocol = OriginalObject()
let objcAction: MyProtocol = ObjCMyProtocolWrap(action)
button.addTarget(objcAction, action: #selector(ObjCMyProtocolWrap.doSomething), for: .touchUpInside)

但请注意:您必须存储对包装对象的引用(本例中为objcAction)! UIButton只有弱引用!