UnRewa
UnRewa

Reputation: 2472

NSMethodSignature in Swift

In ObjC I have:

NSMethodSignature *ms = [[object.target class] instanceMethodSignatureForSelector:object.selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:ms];

In Swift I get error:

'NSObject' does not have a member named 'instanceMethodSignatureForSelector'

When I try this:

var ms:NSMethodSignature? = (object.target.dynamicType as NSObject).instanceMethodSignatureForSelector(object.success)

Upvotes: 1

Views: 4376

Answers (3)

aleclarson
aleclarson

Reputation: 19045

An addon to @matt's answer...

If you have multiple functions with the same name and different parameters, you should ensure that the function reference is pointing to the intended function.

let funcref: () -> () = object.funcName

If you do NOT do this, unexpected things happen (if you don't just get an error). Let's take a look!


Scenario 1:

func doStuff (withThis: Any) {}

func doStuff (withThis: Any, andThis: Any, alsoThis: Any) {}

let funcref = doStuff

In this case, no error is given and funcref is equal to the function with the most parameters.

This only occurs when:

    • One function takes exactly 1 parameter

    • The other function takes more than 1 parameter


Scenario 2:

func doStuff (withThis: Any) {}

func doStuff () {}

let funcref = doStuff

In this case, no error is given and funcref is equal to the function with NO parameters.

This only occurs when:

    • One function takes NO parameters

    • The other function takes exactly 1 parameter


Scenario 3:

func doStuff () {}

func doStuff (withThis: Any) {}

func doStuff (withThis: Any, andThis: Any) {}

func doStuff (withThis: Any, andThis: Any, alsoThis: Any) {}

let funcref = doStuff

In this case, funcref's line will give the error:

Could not find an overload for 'doStuff' that accepts the supplied arguments

This only occurs when:

    • There are more than 3 functions that take 1 or more parameters and have the same name


Scenario 4:

func doStuff () {}

func doStuff (withThis: Any, andThis: Any) {}

let funcref = doStuff

In this case, funcref's line will give the error:

Ambiguous use of 'doStuff'.

This only occurs when:

    • All the above scenarios are not relevant

Upvotes: 1

matt
matt

Reputation: 535547

There are no invocations in Swift. But perhaps you never needed an invocation here:

NSMethodSignature *ms = 
    [[object.target class] instanceMethodSignatureForSelector:object.selector];

So at some time you formed or had access to an object (object) with a target and a selector. This suggests that at that time you could have formed a closure in which you call that method on that target. For example:

let clos = {() -> () in object.someMethod(); return; }

Now you have a value clos of type () -> () that you can store, pass around, and so forth. When the time comes, you just call it:

clos()

Or, depending on the circumstances, you can store a reference to that method directly:

let funcref = object.someMethod

Again, you can later call it:

funcref()

Now that we have closures and functions as first-class linguistic citizens, the dynamism of Objective-C will turn out to have been, in many cases, just a crutch that is no longer needed.

And if you find that you really, really did need it, Objective-C has not gone away and you can mix it into your project.

Upvotes: 5

Sulthan
Sulthan

Reputation: 130122

Getting a method signature is rather easy:

var target = NSObject()
var selector = Selector("success")

var signature: NSMethodSignature? = target.methodSignatureForSelector(selector)

However, using NSInvocation is forbidden:

NSInvocation not available

Rethink your approach.

Upvotes: 3

Related Questions