简体   繁体   中英

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

Sometimes when I am working with selectors in Swift (ie the Selector type), the string literal that I provide for the action parameter to methods like targetForAction(_:withSender:) or addTarget(_:action:) doesn't invoke or map to the actual Swift function to which I am expecting.

For example, when an instance of MyResponder as shown below is in the responder chain, it cannot be found when calling targetForAction(_:withSender) using the string showImage: . What is the pattern for knowing what is the proper string literal to provide for different types of Swift function signatures and the options for required and/or omitted argument labels?

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" )
        }
    }
}

With some trial, error and encouragement from commenters, I managed to figure out the pattern!

The string literal has to follow Objective-C syntax translated from the signature of your Swift function, which is an interesting tidbit that wasn't obvious at first, but makes perfect sense when you consider the purpose things like the @objc attribute. In writing up a better code sample, I seem to have figured out the pattern for the mappings myself.

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

Where what's in the parenthesis is required only when the argument label is required (ie not omitted). And remember to capitalize With and First .

In each of the following examples, myObject will return itself as the target for the provided selector, indicating that the string literal provided as the Selector did in fact map that the Swift function for which it was intended.

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM