使用选择器错误的 Swift 3 协议扩展 [英] Swift 3 protocol extension using selector error

查看:28
本文介绍了使用选择器错误的 Swift 3 协议扩展的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为我的 UIViewController 有一个非常简单的协议扩展,提供了通过点击手势关闭键盘的功能.这是我的代码:

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

@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)
    }
}

问题是上面的代码在这一行抛出了编译错误:

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

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

带有错误信息:

'#selector' 的参数引用未暴露给 Objective-C 的实例方法 'on(tap:)'

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

建议通过在 func on(tap: UITapGestureRecognizer) 之前添加 @objc 来修复它"

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

好的,我添加标签:

@objc func on(tap: UITapGestureRecognizer) {
    dismissKeyboard()
}

但是,它会在这个新添加的 @objc 标签上抛出一个不同的编译错误,并带有错误消息:

But then, it throws a different compile error on this newly added @objc tag with the error message:

@objc 只能与类的成员、@objc 协议和类的具体扩展一起使用

@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes

建议通过删除我刚刚被告知添加的完全相同的标签来修复它".

我最初认为在我的协议定义之前添加 @objc 可以解决任何 #selector 问题,但显然情况并非如此,并且这些循环错误消息/建议不是有丝毫帮助.我一直在疯狂追逐,到处添加/删除 @objc 标签,将方法标记为 optional,将方法放入协议的定义中,等等.

I originally thought adding @objc before my protocol definition would solve any #selector problems but apparently that's not the case, and these cyclical error messages/suggestions aren't helping in the slightest. I've gone down a wild goose chase of adding/removing @objc tags everywhere, marking methods as optional, putting methods in the protocol's definition, etc.

我在协议定义中放什么也无关紧要 保持扩展不变,以下示例不起作用,协议定义中声明的方法的任何组合也不起作用:

It also doesn't matter what I put in the protocol definition Leaving the extension the same, the following example does not work nor does any combination of the declared methods in the protocol's definition:

@objc protocol KeyboardDismissing { 
    func on(tap: UITapGestureRecognizer)
}

这让我误以为它是通过编译为独立协议来工作的,但第二次我尝试将其添加到视图控制器中:

This tricks me into thinking it works by compiling as a stand alone protocol, but the second I try to add it to a view controller:

class ViewController: UIViewController, KeyboardDismissing {}

它吐出原来的错误.

有人可以解释我做错了什么以及我如何编译它吗?

Can someone explain what I'm doing wrong and how I can compile this?

注意:

我看过这个问题但它适用于 Swift 2.2 而不是 Swift 3,一旦您创建一个继承自示例中定义的协议的视图控制器类,答案也不会编译.

I've looked at this question but it is for Swift 2.2 not Swift 3 nor does the answer compile as soon as you create a view controller class that inherits from the protocol defined in the example.

我也看过这个问题但是答案使用 NotificationCenter 这不是我所追求的.

I've also looked at this question but the answer uses NotificationCenter which is not what I'm after.

如果还有其他看似重复的问题,请告诉我.

If there are any other seemingly duplicate questions, please let me know.

推荐答案

这是一个 Swift 协议扩展.Swift 协议扩展对 Objective-C 是不可见的,无论如何;它对它们一无所知.但是 #selector 是关于 Objective-C 查看和调用你的函数.这不会发生,因为您的 on(tap:) 函数在协议扩展中定义.因此,编译器正确地阻止了您.

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.

这个问题是一大类问题之一,人们认为他们会通过尝试将 Objective-C 可调用功能(选择器、委托方法等)注入到类中来巧妙地使用协议扩展来处理 Cocoa通过协议扩展.这是一个吸引人的想法,但它行不通.

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.

这篇关于使用选择器错误的 Swift 3 协议扩展的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆