问题
I'm creating a view programatically, and adding a function so the action responds to the UIControlEvents.TouchUpInside event:
button.addTarget(self, action: action, forControlEvents:
UIControlEvents.TouchUpInside)
So, by going into the documentation I've added this action as a selector:
#selector(ViewController.onRegularClick)
XCode then complaints about:
Argument of #selector refers to a method that is not exposed to Objective-C
So I have to set up the handler function with:
@objc func onRegularClick(sender: UIButton)
Can some one please put this noob on the right direction by guiding me to the documentation, or even give a short explanation, on:
- why can't I no longer pass simply the function name String to the action?
- how is the proper way to implement this following the Swift Way? Using the Selector class?
- why do we need to pass the @objc keyword and how it affects the function?
Thank you!
回答1:
- why can't I no longer pass simply the function name String to the action?
Using strings for selectors has been deprecated, and you should now write #selector(methodName)instead of "methodName". If the methodName() method doesn't exist, you'll get a compile error – another whole class of bugs eliminated at compile time. This was not possible with strings.
- how is the proper way to implement this following the Swift Way? Using the Selector class?
You did it the right way:
button.addTarget(self, action: #selector(ClassName.methodName(_:)), forControlEvents: UIControlEvents.TouchUpInside)
- why do we need to pass the @objc keyword and how it affects the function?
In Swift the normal approach is to bind method's calls and method's bodies at compile time (like C and C++ do). Objective C do it at run time. So in Objective C you can do some things that are not possible in Swift - for example it is possible to exchange method's implementation at run time (it is called method swizzling). Cocoa was designed to work with Objective C approach and this is why you have to inform compiler that your Swift method should be compiled ObjectiveC-like style. If your class inherits NSObject it will be compiled ObjC-like style even without @objc keyword.
回答2:
- Well, it is called evolution
When there are some arguments in the method, you should declare the selector as:
let selector = #selector(YourClass.selector(_:))You can type only
#selector(selector(_:))if the selector is in the same class of the caller._:means that accept one parameter. So, if it accept more parameters, you should do something like:(_:, _:)and so on.I found out that the
@objcis needed only when the function is declared as private or the object doesn't inherit from NSObject
回答3:
1: Currently you can, but it will create a deprecated warning. In Swift 3 this will be an error, so you should fix it soon. This is done because just using a String can not be checked by the compiler if the function really exists and if it is a valid Objective C function which can be resolved dynamically during runtime.
2: Do it in this way:
button.addTarget(self, action: #selector(MyViewControllerClass.buttonPressed(_:)), forControlEvents: UIControlEvents.TouchUpInside)
3: Usually you not have to use the @objc attribute. I assume your class ViewController is (for any reason) not derived from UIViewController. If it derives from UIViewController is inherits also the needed ObjC behavior for calling selectors on functions.
回答4:
For swift3.0 just do like below code :
yourButton.addTarget(self, action: #selector(yourButtonPressed), for: .touchUpInside)
and yourButtonPressed method
@IBAction func yourButtonPressed(sender:UIButton) {
// Do your code here
}
回答5:
Everyones's answers are perfect but I have a better approach. Hope you gonna like it.
fileprivate extension Selector {
static let buttonTapped =
#selector(ViewController.buttonTapped(_:))
}
...
button.addTarget(self, action: .buttonTapped, for: .touchUpInside)
here in this file private will help to show buttonTapped only in file.
回答6:
Programmatically
button.addTarget(self, action: #selector(returnAction), for: .touchUpInside)
// MARK: - Action
@objc private func returnAction(sender: UIButton) {
print(sender.tag)
}
来源:https://stackoverflow.com/questions/36628636/proper-way-to-use-selectors-in-swift