Function in Swift 2 protocol extension returns unrecognized selector when using a UIGestureRecognizer to call it.

So when I try to connect a UIGestureRecognizer's target-action to the handleGesture function I get an unrecognized selector exception.


protocol SomeProtocol: class {
     func handleGesture(gesture: UILongPressGestureRecognizer)

}
extension SomeProtocol where Self: UITableViewController {
    func handleGesture(gesture: UILongPressGestureRecognizer) { . . . }
}


class MasterViewController: UITableViewController, SomeProtocol {
var gesture: UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: "handleGesture:")
}


UPDATE: Bug filed: 22611665

UPDATE (Jan. 8, 2016): bug report (22611665) was closed as a duplicate of another issue (21552427) whose status is open at this time.

Accepted Reply

handleGesture:
is the right selector name. The first parameter in Swift has no external name.

The question is whether functions in protocol extensions can be used with dynamic dispatch - i.e. from ObjC.


In any case all functions you intend to use via selector should be marked with

dynamic
or
@objc
.

If this results in an error that

@objc
cannot be used in this context, then what you are trying to do is simply not supported.


protocol SomeProtocol: class {
    @objc func handleGesture(gesture: UILongPressGestureRecognizer)
}

extension SomeProtocol where Self: UITableViewController {
    @objc func handleGesture(gesture: UILongPressGestureRecognizer) { . . . }
}

Replies

I'm pretty sure


func handleGesture(gesture: UILongPressGestureRecognizer)



has the selector handleGesturegesture:

Ok so I changed the gesture's action to handleIt, which is a method in the class that just calls the method I was trying to connect the gesture to originally. This works but obviously should be unnecessary.


var gesture: UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: "handleIt:")

func handleIt(gesture: UILongPressGestureRecognizer) {
        handleGesture(gesture)
}



handleGesture(gesture) implementation is in the protocol extension...the gesture should be able to attach to it.


This seems like a bug...

handleIt: works? The selector for it should be handleItgesture: The Parameter names are part of the selector.

They aren't according to the documentation: Objective-C Selectors

handleGesture:
is the right selector name. The first parameter in Swift has no external name.

The question is whether functions in protocol extensions can be used with dynamic dispatch - i.e. from ObjC.


In any case all functions you intend to use via selector should be marked with

dynamic
or
@objc
.

If this results in an error that

@objc
cannot be used in this context, then what you are trying to do is simply not supported.


protocol SomeProtocol: class {
    @objc func handleGesture(gesture: UILongPressGestureRecognizer)
}

extension SomeProtocol where Self: UITableViewController {
    @objc func handleGesture(gesture: UILongPressGestureRecognizer) { . . . }
}

Thanks for the input. I recieved this error: "members of protocol extensions cannot be declared @objc"

So this isn't supported. But it should be. 😉

I just ran into this myself (with a NSTimer). It even crashed the compiler when I tried to make the protocol @objc. The work around I used was to pass as a selector a name of a function declared in the main class itself (which turns around and just calls into the protocol defined function). The protocol has a var defined for the selector so it isn't hardcoded into the protocol. A bit of a hack but it works.