您如何知道要提供哪个字符串作为 Swift 函数的选择器?

How do you know which string to provide as a selector for Swift functions?

有时,当我使用 Swift 中的选择器(即 Selector 类型)时,我为 action 参数提供的字符串文字提供给方法 targetForAction(_:withSender:)addTarget(_:action:) 不会调用或映射到我期望的实际 Swift 函数。

例如,当如下所示的MyResponder实例在响应者链中时,使用字符串showImage:调用targetForAction(_:withSender)时无法找到它。了解为不同类型的 Swift 函数签名提供什么是正确的字符串文字以及所需 and/or 省略参数标签的选项的模式是什么?

import UIKit

class MyResponder: UIResponder {

    func showImage( named filename: String ) {
        print( "Loading image..." )
    }
}

class MyViewController: UIViewController {

    @IBAction func buttonTapped( sender: AnyObject? ) {
        if let responder = self.targetForAction( "showImage:", withSender: self ) as? MyResponder {
            responder.showImage(named: "my_image" )
        }
    }
}

在评论者的一些尝试、错误和鼓励下,我设法找出了规律!

字符串文字必须遵循从 Swift 函数的签名翻译而来的 Objective-C 语法,这是一个有趣的花絮,起初并不明显,但当你考虑@objc 属性之类的目的。在编写更好的代码示例时,我似乎已经自己弄清楚了映射的模式。

functionName + (With + First) + : + (second) + :

括号中的内容仅在需要参数标签时才需要(即未省略)。并记得将 WithFirst.

大写

在以下每个示例中,myObject 将 return 本身作为提供的选择器的目标,表明 Selector 提供的字符串文字实际上映射了Swift 预期的功能。

import UIKit

class MyObject : UIResponder {
    func someFunction() {}
    func someFunction(param:String) {}
    func someLabeledFunction(param param:String) {}
    func someTwoArgumentFunction(param1:String, param2:String) {}
    func someTwoArgumentNoLabelFunction(param1:String, _ param2:String) {}
    func someHalfLabeledTwoArgumentFunction(param1 param1:String, _ param2:String) {}
    func someCompletelyLabeledTwoArgumentFunction(param1 param1:String, param2:String) {}
}

let myObject = MyObject()
myObject.targetForAction("someFunction", withSender: nil)
myObject.targetForAction("someFunction:", withSender: nil)
myObject.targetForAction("someLabeledFunctionWithParam:", withSender: nil)
myObject.targetForAction("someTwoArgumentFunction:param2:", withSender: nil)
myObject.targetForAction("someTwoArgumentNoLabelFunction::", withSender: nil)
myObject.targetForAction("someHalfLabeledTwoArgumentFunctionWithParam1::", withSender: nil)
myObject.targetForAction("someCompletelyLabeledTwoArgumentFunctionWithParam1:param2:", withSender: nil)