Benedict Cohen
Benedict Cohen

Reputation: 11920

Is it safe to use objc_msgSend in the follow situation?

I have an object and a selector to invoke on said object. The selector will take one of 4 forms (modelled to be similar to the target-action pattern):

-(void)selectorWithZeroArguments; -(void)selectorWithObject:(id)object; -(void)selectorWithObject:(id)object dictionary:(NSDictionary *)dict; -(void)selectorWithObject:(id)object dictionary:(NSDictionary *)dict string:(NSString *)string; ``` Currently I have a switch as follows:

switch ([[object methodSignatureForSelector:selector] numberOfArguments]) {
    case 2:
        objc_msgSend(object, selector);
        break;

    case 3:
        objc_msgSend(object, selector, otherObject);
        break;

    case 4:
        objc_msgSend(object, selector, otherObject, dictionary);
        break;

    case 5:
        objc_msgSend(object, selector, otherObject, dictionary, string);
        break;
}

```

Would it be safe to remove the switch statement and only use objc_msgSend(object, selector, otherObject, dictionary, string)? My testing suggests that sending additional arguments to objc_msgSend is harmless and I can find no documentation to support or refute this.

Also, is there a better way to approach this problem? I know that I could use NSInvocation but that seems vastly more cumbersome for no gains.

Upvotes: 1

Views: 929

Answers (1)

Benedict Cohen
Benedict Cohen

Reputation: 11920

So with a bit more searching on developer.apple.com and some help from the Objective-C mailing list I've concluded that it is not sensible to call objc_msgSend with additional arguments. However it is fine to use objc_msgSend providing it is cast to the correct function prototype. An example from above:

objc_msgSend(object, selector, otherObject)

should be cast as:

((void(*)(id, SEL, id))objc_msgSend)(object, selector, otherObject);

This cast will allow the compiler to ensure that the stack frames are correctly constructed.

The code for NSInvocation version is comparatively less cumbersome than the casted version so I'll probably uses that. I'm also going to do some benchmarks to satisfy my curiosity.

Documentation:

Upvotes: 2

Related Questions