The correct way to use selectors in Swift

I create the view programmatically and add a function so that the action responds to the UIControlEvents.TouchUpInside event:

button.addTarget(self, action: action, forControlEvents: UIControlEvents.TouchUpInside) 

So, going into the documentation, I added this action as a selector:

 #selector(ViewController.onRegularClick) 

Xcode then complains:

The #selector argument refers to a method that is not exposed by Objective-C

Therefore, I need to configure the handler function with

 @objc func onRegularClick(sender: UIButton) 

Can someone put this noob in the right direction, directing me to the documentation or even giving a brief explanation:

  • Why can't I just pass the name of the String function to the action?
  • How to implement this correctly after Swift Way? Using the Selector class?
  • Why do we need to pass the @objc keyword and how does it affect the function?

Thanks!

+8
source share
5 answers
  • Why can't I just pass the name of the String function to the action?

Using strings for selectors is deprecated, and now you should write #selector(methodName) instead of "methodName" . If the methodName () method does not exist, you will get a compilation error - another class of errors is eliminated during compilation. This was not possible using strings.

  1. How to implement this correctly after Swift Way? Using the Selector class?

You did it right:

button.addTarget(self, action: #selector(ClassName.methodName(_:)), forControlEvents: UIControlEvents.TouchUpInside)

  1. Why do we need to pass the @objc keyword and how does it affect the function?

In Swift, the normal approach is to bind method calls and method bodies at compile time (e.g. C and C ++ do). Goal C do this at runtime. Thus, in Objective-C, you can do some things that are not possible in Swift - for example, you can implement a method implementation at runtime (this is called a swizzling method). Cocoa was designed to work with the Objective-C approach, so you need to tell the compiler that your Swift method must be compiled in Objective-C style. If your class inherits NSObject, it will compile in ObjC style, even without the @objc keyword.

+10
source
  • Well it's called evolution
  • When there are some arguments in a method, you must declare the selector as:

     let selector = #selector(YourClass.selector(_:)) 

    You can only enter #selector(selector(_:)) if the selector is in the same caller class. _: means it takes one parameter. So, if it takes more parameters, you should do something like: (_:, _:) , etc.

  • I found out that @objc needed only when the function is declared as private or the object is not inherited from NSObject

+7
source

1: Currently you can, but it will generate an outdated warning. This will be a bug in Swift 3, so you should fix it soon. This is done because simply using String cannot be verified by the compiler if the function really exists and if it is a valid Objective-C function that can be dynamically resolved at runtime.

2: Do it as follows:

 button.addTarget(self, action: #selector(MyViewControllerClass.buttonPressed(_:)), forControlEvents: UIControlEvents.TouchUpInside) 

3: Normally you do not need to use the @objc attribute. I assume that your ViewController class (for some reason) is not derived from the UIViewController . If it is derived from a UIViewController , it also inherits the required ObjC behavior to invoke function selectors.

+2
source

For swift3.0 just follow the code below:

  yourButton.addTarget(self, action: #selector(yourButtonPressed), for: .touchUpInside) 

and yourButtonPressed method

 @IBAction func yourButtonPressed(sender:UIButton) { // Do your code here } 
+1
source

All the answers are perfect, but I have a better approach. I hope, you 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 show buttonTapped only in the file.

0
source

All Articles