3

I would like a parent ViewController to handle Target-Actions generated by one of its child ViewControllers.

According to the Apple docs this should be possible by setting target to nil and following the responder chain.

If you specify nil for the target object, the control searches the responder chain for an object that defines the specified action method. https://developer.apple.com/documentation/uikit/uicontrol

But how do I write the action method signature when target is nil?

Typically you enclose the function name in #selector() which gives you compile time checks that a method exists with that signature. Like so:

class MyViewController: UIViewController {
    override func viewDidLoad() {
         self.button.addTarget(self, action: #selector(buttonPressed(sender:)), for: .touchDown)
    }

    func buttonPressed(sender: UIButton) { }

}

But since target is nil the compiler complains because it can't find it:

// ! Use of unresolved identifier "buttonPressed(sender:)"
button.addTarget(nil, action: #selector(buttonPressed(sender:)), for: .touchDown)

I tried initializing a Selector using a String, but the compiler also complains.

    // ! String literal is not a valid Objective-C selector
    button.addTarget(nil, action: Selector("buttonPressed(sender:)"), for: .touchDown)
MH175
  • 1,831
  • 1
  • 14
  • 28

2 Answers2

3

The solution is to prefix with the name of the defining class.

    button.addTarget(nil, action: #selector(MyViewController.buttonPressed(sender:)), for: .touchDown)

FYI I got the answer through this nice blog post from Jan 2016, downloading the source files, and having XCode convert it to Swift 3 syntax :-)

MH175
  • 1,831
  • 1
  • 14
  • 28
  • 4
    But this surely defeats the point: that a responder can respond to the selector without a responder being explicitly pre-defined.. – Aodh Jan 08 '18 at 00:05
  • How do you mean? Because now the selector must be a method defined in `MyViewController`? I want my child's actions to be handled by its parent, so I want my selector to be defined in the parent. – MH175 Jan 09 '18 at 01:54
  • 5
    The idea of the responder chain mechanism is that a responder is the first in a chain of possible responders without explicitly naming which responder will respond, allowing for loose coupling.. – Aodh Jan 09 '18 at 20:51
0

This works for me, note double parentheses to avoid warning: NSApp.sendAction(Selector(("enterActivationNumber:")), to: nil, from: sender)