It seems like there should be an easy way to call a selector with some arguments when all you have is a SEL object. I can't seem to find the correct syntax.
-(MyClass*) init: (SEL)sel owner:(NSObject*) parent
{
int i =10;
[parent performSelector:sel:i ];
}
Take a look at the NSObject
documentation. In this case:
[parent performSelector:sel withObject:[NSNumber numberWithInt:i]];
(note this method is actually listed in the NSObject
protocol documentation). Since -[NSObject performSelector:withObject:]
requires an object argument, you will have to write a wrapper in parent's class like
-(void)myMethodForNumber:(NSNumber*)number {
[self myMethod:[number intValue]];
}
to unbox the NSNumber
.
If you really want to invoke a method that takes non-object arguments directly (for example, you don't have control of the callee source and don't want to add a category), you can use NSInvocation
:
NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[parent methodSignatureForSelector:sel]];
[inv setSelector:sel];
[inv setTarget:parent];
[inv setArgument:&i atIndex:2]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
[inv invoke];
On a side note, your method looks like an init
method, but does not follow the correct initializer pattern for Objective-C. You need to call the super-classes initializer, and you need to test for a nil
result from that call and you must return self from the initializer method. In all cases, your Objective-C initializer methods should look like:
-(id)myInitMethod {
self = [super init];
if(self != nil) {
//perform initialization of self
}
return self;
}
Your method (if it's an init method) would then look like:
-(id) init: (SEL)sel owner:(NSObject*) parent
{
self = [super init];
if(self != nil) {
int i = 10;
NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[parent methodSignatureForSelector:sel]];
[inv setSelector:sel];
[inv setTarget:parent];
[inv setArgument:&i atIndex:2]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
[inv invoke];
}
return self;
}
To be more Objective-C stylistically, I would rename the initializer -(id)initWithSelector:owner:
as well.
what Barry Wark said is great.. i have just modified the discussion for lazy programmers
-(void)myMethodWith:(int)number andBOOL:(BOOL) someBool andStr:(NSString *)str{
NSLog(@"%d %d %@",number,someBool,str);
}
-(void) testMethod{
SEL sel = @selector(myMethodWith:andBOOL:andStr:);
int i = 10;
BOOL bol = YES;
NSString *str = @"hey baby !";
NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:sel]];
[inv setSelector:sel];
[inv setTarget:self];
[inv setArgument:&i atIndex:2]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
[inv setArgument:&bol atIndex:3];
[inv setArgument:&str atIndex:4];
[inv invoke];
}
You want to use performSelector:withObject:
The tricky part is converting the int
to an NSObject. You cannot use performSelector
with messages that take int
params, it must instead take an id
.
From the NSObject Protocol Reference:
aSelector should identify a method that takes a single argument of type id. For methods with other argument types and return values, use NSInvocation.
Once that change is made, you can do:
id arg = [NSNumber numberWithInt:10];
[parent performSelector:sel withObject:arg];
You can use:
- (id)performSelector:(SEL)aSelector withObject:(id)anObject
- (id)performSelector:(SEL)aSelector withObject:(id)anObject withObject:(id)anotherObject
Or if you need to use more complex method use NSInvocation
class
For methods that take one or two objects of type id
as arguments, you can use:
[parent performSelector:sel withObject:argument1];
or
[parent performSelector:sel withObject:argument1 withObject:argument2];
For methods with other argument types, create an NSInvocation
that can encapsulate arbitrary method calls.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With