-
-
Save Akhrameev/f8cd4d72343d933a68a18ef1d24e3f2f to your computer and use it in GitHub Desktop.
You want to use NSObject performSelector with multiple parameters, but you can't ? (1)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- ( id ) methodWithOneParam:( id ) theParam { | |
// Do amazing stuff | |
return @"Srsly, Amazing!"; | |
} | |
- ( id ) methodWithFirst:( id ) firstParam | |
andSecond:( id ) secondParam | |
{ | |
// Do doubly amazing stuff | |
return @"Even Amazinger"; | |
} | |
- ( id ) methodWithFirst:( id ) firstParam | |
andSecond:( id ) secondParam | |
andThird:( id ) thirdParam | |
{ | |
// Do thricely amazing stuff that will certainly rock. | |
return @"MOAR AMAZINGER-ER!"; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
id first = nil; | |
id second = nil; | |
id third = nil; | |
id result = nil; | |
// easy peasy to do the first one. | |
SEL singleParamSelector = @selector(methodWithOneParam:); | |
result = [self performSelector:singleParamSelector // https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html | |
withObject:first]; | |
NSLog(@"%@", result); | |
/* | |
Let's get a bit trickier and get the selector signature | |
from a string this tine | |
*/ | |
SEL doubleParamSelector | |
= NSSelectorFromString(@"methodWithFirst:andSecond:"); | |
result = [self performSelector: doubleParamSelector | |
withObject: first | |
withObject: second]; | |
NSLog(@"%@", result); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- ( id ) boringMethod:( NSDictionary *) args { | |
id first = [args objectForKey:@"first" ]; | |
id second = [args objectForKey:@"second"]; | |
id third = [args objectForKey:@"third" ]; | |
return @"Whatever"; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
NSInvocation * invocation; // https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/DistrObjects/Tasks/invocations.html#//apple_ref/doc/uid/20000744-CJBBACJH | |
NSMethodSignature * methSig; // http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSMethodSignature_Class/Reference/Reference.html | |
SEL triParamSelector; | |
/* | |
We need both a selector and a method signature, | |
they are different. A method signature contains | |
information about the number and types of arguments | |
a method takes, whereas a selector is just a name. | |
*/ | |
triParamSelector = @selector(methodWithFirst:andSecond:andThird:); | |
methSig = [self methodSignatureForSelector: triParamSelector]; | |
invocation = [NSInvocation invocationWithMethodSignature: methSig]; | |
/* | |
Set the target (the object to invoke the | |
selector on) and the selector to invoke | |
*/ | |
[invocation setSelector: triParamSelector]; | |
[invocation setTarget: self]; | |
/* | |
Now we have to set up the arguments. Note that we | |
have to start from 2, because there are two 'hidden' | |
arguments, which we'll get to shortly | |
*/ | |
[invocation setArgument: &first atIndex: 2]; | |
[invocation setArgument: &second atIndex: 3]; | |
[invocation setArgument: &third atIndex: 4]; | |
/* | |
Now make the call and get the returned value. | |
*/ | |
[invocation invoke]; | |
[invocation getReturnValue: &result]; | |
NSLog(@"NSInvocation : %@", result); | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SEL betterWaySelector | |
= NSSelectorFromString(@"methodWithFirst:andSecond:andThird:"); | |
IMP methodImplementation // https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html | |
= [self methodForSelector: betterWaySelector]; | |
result = methodImplementation( self, | |
betterWaySelector, | |
first, | |
second, | |
third ); | |
NSLog(@"methodForSelector : %@", result); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SEL evenBetterWay | |
= NSSelectorFromString(@"methodWithFirst:andSecond:andThird:"); | |
result = objc_msgSend( self, | |
evenBetterWay, | |
first, | |
second, | |
third ); | |
NSLog(@"objc_msgSend : %@", result); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- ( void ) beware:( float ) whoops { | |
NSLog(@"%f", whoops); | |
} | |
- ( float ) incrementFloat:( float ) digits { | |
return digits + 1.0; | |
} | |
- ( void ) carefulNow { | |
SEL selector = @selector(beware:); | |
IMP method = [self methodForSelector: selector]; | |
float test = 123.456; | |
/* works, obvs */ | |
[self beware: test]; | |
/* | |
123.456001 | |
*/ | |
/* bork */ | |
objc_msgSend( self, selector, test); | |
/* | |
0.000000 | |
*/ | |
/* bork */ | |
method( self, selector, test ); | |
/* | |
0.000000 | |
*/ | |
/* works */ | |
((void (*) (id, SEL,float))method)(self,selector,test); | |
/* | |
123.456001 | |
*/ | |
/* works */ | |
((void (*) (id, SEL, float))objc_msgSend)(self,selector,test); | |
/* | |
123.456001 | |
*/ | |
selector = @selector(incrementFloat:); | |
float result | |
= ((float (*)(id,SEL,float))objc_msgSend)(self,selector,test); | |
NSLog(@"%f", result); | |
/* | |
124.456001 | |
*/ | |
method = [self methodForSelector:selector]; | |
result = ((float (*) (id, SEL, float))method)(self,selector,test); | |
NSLog(@"%f", result); | |
/* | |
124.456001 | |
*/ | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment