prabodhprakash
prabodhprakash

Reputation: 3917

calling class_respondsToSelector for a Swift class method from Objective-C code

I have a Swift class as below

class ViewController: UIViewController {
    func helloWorld(a: String)
    {
        print(a);
    }
}

Assuming my target name is Pebble, from an objective-c class, I need to find out, if the class ViewController responds to selector helloWorld:. I have tried the following statements:

class_respondsToSelector(NSClassFromString(@"Pebble.ViewController"), NSSelectorFromString(@"helloWorld"))
class_respondsToSelector(NSClassFromString(@"Pebble.ViewController"), NSSelectorFromString(@"helloWorld:"))
class_respondsToSelector(NSClassFromString(@"ViewController"), NSSelectorFromString(@"helloWorld:"));
class_respondsToSelector(NSClassFromString(@"ViewController"), NSSelectorFromString(@"helloWorld"));

However,

1) In ViewController when I write let responds = self.responds(to: Selector("helloWorld:")) - it returns true.

2) In AppDelegete when I write let responds = ViewController.responds(to: Selector("helloWorld:")) - it returns false.

3) In AppDelegete when I write let responds = ViewController.instancesRespond(to: Selector("helloWorld:")) - it returns false.

All of the above returns NO. What should be done to fix this or what is the error?

Upvotes: 1

Views: 715

Answers (2)

Andreas
Andreas

Reputation: 2715

Some suggestions I can think of:

  • Annotate your class, `@objc(ViewController), to make sure it is exposed with the right name
  • Qualify your selector with the parameter name, i.e. helloWorld(a:)

Upvotes: 0

OOPer
OOPer

Reputation: 47876

Try this:

class_respondsToSelector(NSClassFromString(@"{YOUR_MODULE_PRODUCT_NAME}.ViewController"), NSSelectorFromString(@"helloWorldWithA:"))

In Swift 3, the first argument label is a part of method signature and when generating Objective-C selector it is concatenated with "With", so, the default Objective-C selector for func helloWorld(a: String) becomes helloWorldWithA:.

If you do not like this behaviour, you can write your helloWorld as func helloWorld(_ a: String), and its Objective-C selector becomes helloWorld:.

Or you can specify Objective-C selector explicitly with @objc annotation. Writing like @objc(helloWorld:) func helloWorld(a: String), the Objective-C selector for it becomes helloWorld: as specified.

Upvotes: 2

Related Questions