栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

如何使用Swift #selector语法解决“模棱两可的使用”编译错误?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

如何使用Swift #selector语法解决“模棱两可的使用”编译错误?

[ 注意 此答案最初是在Swift 2.2下提出的。它已针对Swift
4进行了修订,涉及两个重要的语言更改:第一个方法参数external不再被自动抑制,并且选择器必须显式地暴露给Objective-C。

您可以解决这个问题,通过 铸造 你的函数引用正确的方法签名:

let selector = #selector(test as () -> Void)

(但是,我认为您不必这样做。我认为这种情况是一个错误,表明Swift引用函数的语法不足。我提交了错误报告,但无济于事。)


只是总结一下新

#selector
语法:

此语法的目的是为了防止在将选择器作为文字字符串提供时可能会发生的通用运行时崩溃(通常是“无法识别的选择器”)。

#selector()
接受一个
函数引用 ,编译器将检查该函数是否确实存在,并将为您解析对Objective-C选择器的引用。因此,您不能轻易犯任何错误。

编辑:
好的,是的。您可以成为一个完全笨拙的人,并将目标设置为一个实例,该实例未实现由所指定的操作消息

#selector
。编译器不会阻止您,并且您将崩溃,就像在过去的美好时光。

函数引用可以三种形式出现:

  • 函数的 裸名 。如果功能是明确的,这就足够了。因此,例如:
        @objc func test(_ sender:AnyObject?) {}    func makeSelector() {        let selector = #selector(test)    }

只有一种

test
方法,因此
#selector
即使它需要一个参数并且
#selector
没有提到该参数,也要引用它。解析后的Objective-
C选择器在幕后仍将正确存在
"test:"
(带有冒号,指示一个参数)。

  • 函数的名称 及其签名 的其余部分。例如:
        func test() {}    func test(_ sender:AnyObject?) {}    func makeSelector() {        let selector = #selector(test(_:))    }

我们有两种

test
方法,因此我们需要区分;该表示法
test(_:)
解析为 第二 个,带有参数的表示法。

  • 带有或不带有其签名的其余部分的功能,再加上名 ,显示 类型 的参数。从而:
        @objc func test(_ integer:Int) {}    @nonobjc func test(_ string:String) {}    func makeSelector() {        let selector1 = #selector(test as (Int) -> Void)        // or:        let selector2 = #selector(test(_:) as (Int) -> Void)    }

在这里,我们 超载了

test(_:)
。超载不能接触到的Objective-C,因为Objective-
C中不允许超载,所以只有一个被暴露出来,我们可以形成只为一个选择 暴露出来,因为选择是一个Objective-C功能。但是就Swift而言,我们
仍然 必须消除歧义,而演员阵容就是这样做的。

(在我看来,正是这种语言功能被误用了,作为上述答案的基础。)

另外,您可能需要通过告诉函数该函数所在的类来帮助Swift解析函数引用:

  • 如果该类与该类相同,或者在该类的超类链的上游,则通常不需要进一步的解决方法(如上例所示);您可以选择

    self
    使用点号(,例如)说出来,
    #selector(self.test)
    在某些情况下,您可能必须这样做。

  • 否则,您可以使用点标记来引用对其实现了该方法的 实例 ,如下面的真实示例(

    self.mp
    是MPMusicPlayerController):

    let pause = UIBarButtonItem(barButtonSystemItem: .pause, target: self.mp, action: #selector(self.mp.pause))

…或者您可以使用 类名 ,并使用点符号:

        class ClassA : NSObject {        @objc func test() {}    }    class ClassB {        func makeSelector() { let selector = #selector(ClassA.test)        }    }

(这似乎是一种奇怪的表示法,因为您似乎在说的

test
是类方法而不是实例方法,但是尽管如此,它将正确地解析为选择器,这很重要。)



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/436380.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号