2

When i pass a static/class method in selector param of UIAccessibilityCustomAction, it is not getting triggered. The same method works for gesture recognizers/add targets functions

The custom action is set and announced properly. So there's no problem in set up of that. But when i double tap staticTest is not triggered. If i pass instance method to it, it works.

Code set-up which is not working:

// does not work
        newView.accessibilityCustomActions?.append(
            UIAccessibilityCustomAction(
                name: "staticTest test action",
                target: ViewController.self,
                selector: #selector(ViewController.staticTest)))

Code Sample:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let newView = UIView(frame: CGRect(x: 20, y: 20, width: 300, height: 300))
        newView.backgroundColor = UIColor.red
        view.isUserInteractionEnabled = true
        view.addSubview(newView)
        newView.isAccessibilityElement = true

        // works
        newView.addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: #selector(instanceTest)))

        // works
        newView.accessibilityCustomActions = [
            UIAccessibilityCustomAction(name: "instanceTest test action", target: self, selector: #selector(instanceTest))
        ]

        // works
        newView.addGestureRecognizer(
            UITapGestureRecognizer(
                target: ViewController.self,
                action: #selector(ViewController.staticTest)))

        // does not work
        newView.accessibilityCustomActions?.append(
            UIAccessibilityCustomAction(
                name: "staticTest test action",
                target: ViewController.self,
                selector: #selector(ViewController.staticTest)))
    }

    @objc static func staticTest() -> Bool {
        print("staticTest")
        return true
    }

    @objc func instanceTest() -> Bool {
        print("InstanceTest")
        return true
    }
}

gsp1294
  • 87
  • 1
  • 9

1 Answers1

0

I tried your code and it was difficult to believe the observation. Then I checked the apple docs and here is my analysis.

Even though apple documentation is silent on the use of static/class function as selector. It's kind of indirectly mentioned in the wordings. https://developer.apple.com/documentation/uikit/uiaccessibilitycustomaction/1620499-init

For UIAccessibilityCustomAction: target:The object that performs the action. selector:The selector of target to call when you want to perform the action.

In your code, target is the ViewController object but it's difficult to say that selector belongs to this object as it's a static/class function. Actually, swift doesn't even allow to call static function using an object. Having said that, it's debatable why static function works with gestureRecogniser. https://developer.apple.com/documentation/uikit/uigesturerecognizer/1624211-init

The defintion of target is slightly different here. target: An object that is the recipient of action messages sent by the receiver when it recognizes a gesture. action: A selector that identifies the method implemented by the target to handle the gesture recognized by the receiver.

So, your code matches the target definiton completely as self is the object which should receive the gesture. But action definition is not completely matched as the target(which is an object and not a class) actually does not implement the static function.

As per my understanding, static function needs to be avoided as selector based on the documentation.

IFTTT
  • 186
  • 6
  • 2
    The documentation you linked clearly mentions: The selector of target to call when you want to perform the action. The method signature must take one of the following forms: `- (BOOL)myPerformActionMethod` `- (BOOL)myPerformActionMethod:(UIAccessibilityCustomAction *)action` These are objective-C *instance* method signatures , not class methods. – Kamil.S Jun 26 '20 at 12:20
  • Nice catch. This makes it clearly evident that static function is not allowed for UIAccessibilityCustomAction. But, gestureRecogniser's behaviour remains questionable. Unlike accessibility action, it does not not have selector as an accessible member so selector description is not mentioned in documentation and as such it's difficult to reason why gesture recognisers accept static function. – IFTTT Jun 26 '20 at 13:05
  • Btw you can invoke In Swift class("static") selector methods using this approach: https://stackoverflow.com/a/43714950/5329717 Cumbersome, but does the job if you *really* need it. – Kamil.S Jun 26 '20 at 13:59
  • I missed to notice the instance method signatures given in doc. Will use instance methods only as that's what is recommended by apple. Thanks for the help @Kamil.S and IFTTT. – gsp1294 Jun 27 '20 at 13:09