Reputation: 11920
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
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