Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
426 views
in Technique[技术] by (71.8m points)

iphone - SEL performSelector and arguments

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  ];
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...