Proper way to use selectors in Swift

josetapadas picture josetapadas · Apr 14, 2016 · Viewed 16.7k times · Source

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:

  1. why can't I no longer pass simply the function name String to the action?
  2. how is the proper way to implement this following the Swift Way? Using the Selector class?
  3. why do we need to pass the @objc keyword and how it affects the function?

Thank you!

Answer

Avt picture Avt · Apr 14, 2016
  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.

  1. 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)

  1. 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.