美文网首页iOS 杂谈
第八篇:对protocol做extinction添加#selec

第八篇:对protocol做extinction添加#selec

作者: jeckHao | 来源:发表于2017-07-21 17:03 被阅读35次

    I have what I thought to be a very simple protocol extension for my UIViewController
    s providing the capability to dismiss a keyboard through a tap gesture. Here's my code:

    protocol Tappable {
        func addTapGestureRecognizer()
        func tapGestureDetected(gesture:UITapGestureRecognizer)
    }
    
    extension Tappable where Self: UIView {
        func addTapGestureRecognizer() {
            let gesture = UITapGestureRecognizer(target: self, action:#selector(Tappable.tapGestureDetected(_:)))
            addGestureRecognizer(gesture)
        }
    }
    
    class TapView: UIView, Tappable {
        func tapGestureDetected(gesture:UITapGestureRecognizer) {
            print("Tapped")
        }
    }
    

    The problem is that the above code throws a compile error on this line:

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

    With the error message:
    Argument of '#selector' refers to instance method 'on(tap:)' that is not exposed to Objective-C

    with the suggestion to "fix it" by adding @objc
    before func on(tap: UITapGestureRecognizer)

    这个问题我搞了2天,才放弃了,下面是一个比较能说服我的理由:

    This is a Swift protocol extension. Swift protocol extensions are invisible to Objective-C, no matter what; it knows nothing of them. But #selector is about Objective-C seeing and calling your function. That is not going to happen because your on(tap:) function is defined only in the protocol extension. Thus the compiler rightly stops you.
    This question is one of a large class of questions where people think they are going to be clever with protocol extensions in dealing with Cocoa by trying to inject Objective-C-callable functionality (selector, delegate method, whatever) into a class via a protocol extension. It's an appealing notion but it's just not going to work.

    翻译后是这个样子的:

    这是一个快速的协议扩展。快速的协议扩展对于objective - c是看不见的,无论如何,它对它们一无所知。但是# selector是关于objective - c查看和调用你的函数。这不会发生,因为您的on(tap:)函数只在协议扩展中定义。因此编译器正确地阻止了你。
    这个问题是一个很大的问题,人们认为在处理可可的过程中,他们会聪明地使用协议扩展,试图通过协议扩展将objective - c - callable功能(选择器、委托方法等)注入到类中。这是一个有吸引力的概念,但它是行不通的。

    最后说一句:

    在extinction协议的时候,尽量使用block,不要使用#selector了,使用回调虽然麻烦了一下,这也是一个曲线救国的方法吧。

    相关资料链接地址

    相关文章

      网友评论

        本文标题:第八篇:对protocol做extinction添加#selec

        本文链接:https://www.haomeiwen.com/subject/lidfkxtx.html