理解 Swift 2.2 选择器语法 - #selector()

Understanding Swift 2.2 Selector Syntax - #selector()

我正在将项目的语法切换到 Swift 2.2(xCode 帮助我自动完成);但是,我不明白新的 #selector() 语法。

举个例子:

timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, 
             selector: #selector(MyVC.timerCalled(_:)), //new selector syntax!
             userInfo: nil, repeats: true)

这有选择器#selector(MyVC.timerCalled(_:))

_: 是什么意思?你能在这个选择器中添加其他变量吗?说,#MyVC.timerCalled(_:whateverVar).

非常感谢有关此语法与早期版本 Swift 中基于字符串的实现的不同之处的一般信息。

这是 Swift 方法签名在文档中的表示方式,它现在开始用于新的语言功能,例如 #selector() 语法,通过参数列表表示方法。

每个冒号(:)代表一个方法参数。对于命名参数,冒号前面是外部参数名称;对于未命名的参数,使用下划线 (_)。

因此,例如,MyVC.timerCalled(_:)) 表示 MyVC 类型上带有一个未命名参数的方法,可以这样声明:

func timerCalled(timer: NSTimer) { ... }

(注意 timer 内部 参数名称,因为默认情况下方法的第一个参数是未命名的)

类型(在您的示例中为 MyVC)如果在 #selector() 声明的相同范围内,也可以省略。

一个更复杂的示例可能如下所示:

let sel = #selector(aMethodWithSeveralParameters(_:secondParam:thirdParam:))

...

func aMethodWithSeveralParameters(firstParam: Int, secondParam: Int, thirdParam: Int) { ... }

括号中的位是一种用于识别所需选择器的参数列表的机制。

我建议您查看 Swift Evolution 中的 Generalized Naming 提案。它涵盖了您拥有许多仅参数标签不同并且需要引用它们的函数的情况。该文档中的示例是:

extension UIView {
  func insertSubview(view: UIView, at index: Int)
  func insertSubview(view: UIView, aboveSubview siblingSubview: UIView)
  func insertSubview(view: UIView, belowSubview siblingSubview: UIView)
}

如果您想获得其中之一的函数值,结果是不明确的:

let fn = someView.insertSubview // ambiguous: could be any of the three methods

实施的解决方案是在生成函数值的代码中添加参数标签,不带任何类型信息,以消除您想要的歧义:

let fn = someView.insertSubview(_:at:)
let fn1 = someView.insertSubview(_:aboveSubview:)

看到括号中的标签是如何添加的了吗?

此提案在最直接适用于您的问题的提案中发挥了作用:

Referencing the Objective-C selector of a method

在这种特殊情况下,您要引用的选择器是 timerCalled:,它是一个没有标签的参数的函数。因此 (_:)。下划线表示未指定标签和冒号。

Swift 2.2 已弃用字符串化选择器:在 swift 2.0 中,我们习惯将选择器编写为字符串,即 "buttonClicked"。这种方法的缺点是编译器无法在编译时检查该方法是否真的存在(即使你拼错了)。

EX:1

func buttonClicked(){
}

所以新方法中的上述方法可以称为#selector(buttonClicked)

EX:2

func buttonClicked(stringValue : String){
}

所以新方法中的上述方法可以称为#selector(buttonClicked(_:))

EX:3

func buttonClicked(stringValue : String, indexValue : Int){
}

所以在新的方法中上面的带参数的方法可以被调用为#selector(buttonClicked(_:indexValue:))

考虑使用以下代码将目标添加到 swift 3 中的按钮,使用 #selector

button.addTarget(self, action: #selector(self.buttonAction(sender:)),
                       for: UIControlEvents.touchUpInside)

 func buttonAction(sender:UIButton!){

 }

迁移到 swift 3

时,此语法对我有用