Thizzer
Thizzer

Reputation: 16673

Calling Method using reflection

As I understand reflection in Swift is poorly available as of yet. I am currently in the process of converting objective-c code to swift for the sake of performance (I have noticed a considerable difference).

Now what I need is a way to call a Method using reflection. The object the method needs to be called upon extends NSObject to enable the class to be resolved using the following code;

let clazz = NSClassFromString("MyProject.DynamicClass") as NSObject.Type; 
let clazzInstance = clazz() as! NSObject;

I am able to retrieve a the number of argument and a reference to the method using the following code;

let selectorMethod = Selector("myCustomMethod:");

let numberOfArguments : UInt32 = method_getNumberOfArguments(selectorMethod);
let referenceToMethod : Method = class_getInstanceMethod(clazz, selector!);

But how do I use/call the referenceToMethod?

Additional
I have also tried calling performSelector but this has been completely removed Swift 2. I also would like to prevent the use of any @objc attributes/annotations.

Upvotes: 4

Views: 3810

Answers (2)

Zell B.
Zell B.

Reputation: 10296

If you are looking for a completely Swifty way of reflection, the object that has the method that needs to be called does not need to be a NSObject at all, instead all it need is a required initializer. Have a look at below example :

class A {
    required init() {}

    func printSomething(s: String) {
        print(s)
    }
}

// initializing object dynamically from class
let clazz = NSClassFromString("MyProject.A") as! A.Type   
let clazzInstance = clazz()

// getting and calling its methods in Swifty way    
let method = clazzInstance.printSomething 
method("something")

The advantage of using this stands on fact that you wont need to use casting at all and also calling method with wrong arguments would trigger a compile time error

Upvotes: 2

RoyBS
RoyBS

Reputation: 1281

A crazy idea, and not perfect:

you can define a var as:

var myFunctionToBe : (() -> AnyObject)?

or even set AnyObject as parameter, and then in the initiator:

init() {
    myFunctionToBe = {
       //do something
       return whatsdone
    }
}

then in reflection you can see the var myFunctionToBe, get it as:

let method = c.value as? (() -> AnyObject)

and invoke it:

method!()

or

let returnVal = method!() as? String

Upvotes: 1

Related Questions