Proper way to use selectors in Swift
- 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
@objc
is needed only when the function is declared as private or the object doesn't inherit from NSObject
- 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 does 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 the compiler that your Swift method should be compiled in Objective-C-like style. If your class inherits NSObject it will be compiled ObjC-like style even without @objc keyword.
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.