【问题标题】:Understanding Swift 2.2 Selector Syntax - #selector()理解 Swift 2.2 选择器语法 - #selector()
【发布时间】:2016-03-22 22:14:30
【问题描述】:

我正在将项目的语法切换到 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 swift2 selector


【解决方案1】:

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

我建议您查看来自 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:,它是一个没有标签的参数的函数。因此 (_:)。下划线表示不指定标签和冒号。

【讨论】:

    【解决方案2】:

    Swift 2.2 已弃用 Stringified 选择器:在 swift 2.0 中,我们使用将选择器编写为 String 即 "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 2.2 时将您的上述示例修复/更改为 #selector(YourClass.buttonClicked) 而不仅仅是 #selector(buttonClicked) 。 2有区别吗?谢谢
    • @crashoverride777 我想你的问题在这里解释得很清楚..stackoverflow.com/questions/24007650/selector-in-swift?rq=1
    • 我认为你总是需要在方法声明前加上@objc
    【解决方案3】:

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

    button.addTarget(self, action: #selector(self.buttonAction(sender:)),
                           for: UIControlEvents.touchUpInside)
    
     func buttonAction(sender:UIButton!){
    
     }
    

    迁移到 swift 3 时,此语法对我有用

    【讨论】:

      【解决方案4】:

      这是 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) { ... }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-21
        • 2016-07-11
        • 2017-01-05
        相关资源
        最近更新 更多