Swift中的@selector()?

Swift中的@selector()?,第1张

Swift中的@selector()?

Swift 本身 不使用选择器-在Objective-C中,使用选择器的几种设计模式在Swift中的工作方式有所不同。(例如,在协议类型

is
/
as
测试上使用可选链接代替
respondsToSelector:
,并在可能的地方使用闭包代替,
performSelector:
以提高类型/内存的安全性。)

但是仍然有许多重要的基于ObjC的API使用选择器,包括计时器和目标/ *** 作模式。Swift提供了

Selector
使用这些类型的类型。(Swift自动使用它代替ObjC的
SEL
类型。)

在Swift 2.2(Xpre 7.3)和更高版本(包括Swift 3 / Xpre 8和Swift 4 / Xpre 9)中:

您可以

Selector
使用
#selector
表达式从Swift函数类型构造一个。

let timer = Timer(timeInterval: 1, target: object,       selector: #selector(MyClass.test),       userInfo: nil, repeats: false)button.addTarget(object, action: #selector(MyClass.buttonTapped),      for: .touchUpInside)view.perform(#selector(UIView.insertSubview(_:aboveSubview:)),  with: button, with: otherButton)

这种方法的好处是什么?Swift编译器会检查函数引用,因此您只能将

#selector
表达式与实际存在且有资格用作选择器的类/方法对一起使用(请参见下面的“选择器可用性”)。您还可以根据功能类型命名的Swift
2.2+规则,
随意根据需要指定功能。

(这实际上是对ObjC

@selector()
指令的改进,因为编译器的
-Wundeclared-selector
检查仅验证命名选择器是否存在。传递给您的Swift函数引用将
#selector
检查是否存在,类的成员身份和类型签名。)

对于传递给

#selector
表达式的函数引用,还有一些其他警告:

  • 使用上述函数引用语法(例如
    insertSubview(_:at:)
    vs
    insertSubview(_:aboveSubview:)
    ),可以通过其参数标签来区分具有相同基本名称的多个函数。但是,如果一个函数没有参数,消除歧义的唯一方法是使用
    as
    带有该函数的类型签名的类型转换(例如
    foo as () -> ()
    vs
    foo(_:)
    )。
  • Swift 3.0+中的属性getter / setter对有一种特殊的语法。例如,给定a
    var foo: Int
    ,您可以使用
    #selector(getter: MyClass.foo)
    #selector(setter: MyClass.foo)
一般注意事项:

情况下

#selector
无法正常工作,并命名:有时候你没有一个函数的引用,使一个选择器(例如,用在ObjC运行时动态注册的方法)。在这种情况下,您可以
Selector
从字符串构造a
:例如
Selector("dynamicMethod:")
-尽管您丢失了编译器的有效性检查。执行此 *** 作时,需要遵循ObjC命名规则,包括
:
每个参数的冒号()。

选择器可用性:选择器 引用的方法必须公开给ObjC运行时。在Swift
4中,每个公开给ObjC的方法都必须在其声明的前面加上

@objc
属性。(在以前的版本中,某些情况下您可以免费获得该属性,但是现在您必须显式声明它。)

请记住,

private
符号也不会暴露给运行时-您的方法至少需要具有
internal
可见性。

关键路径: 这些 路径 与选择器相关,但并不完全相同。Swift 3中也有一种特殊的语法:eg

chris.valueForKeyPath(#keyPath(Person.friends.firstName))
。有关详细信息,请参见SE-0062。还有
KeyPath
Swift
4中的更多内容,因此请确保您使用的是正确的基于KeyPath的API,而不是适当的选择器。

您可以在“ 将Swift与Cocoa和Objective-C结合使用”中的“ 与Objective-C
API交互”下阅读有关选择器的更多信息。 __

注意: 在Swift
2.2之前,它

Selector
遵循
StringLiteralConvertible
,因此您可能会发现旧代码,其中裸露的字符串被传递到采用选择器的API。您将需要在Xpre中运行“转换为当前的Swift语法”以使用
#selector



欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/4913298.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-12
下一篇 2022-11-12

发表评论

登录后才能评论

评论列表(0条)

保存