在 iOS中可以直接调用某个对象的消息 方式有2种:一种是performSelector:withObject:,再一种就是NSInvocation.
第一种方式比较简单,能完成简单的调用。运行时调用方法都是只接受一个或两个参数,如:
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
但是对于大于2个的参数或者有返回值的处理,那就需要做些额外工作才能搞定。那么在这种情况下,我们就可以使用NSInvocation来进行这些相对复杂的操作,NSInvocation可以处理参数、返回值.简单一点理解就是在运行时可以动态决定传入的参数个数,并执行相应的方法.
/**
* 1:基本使用
*/
-(void)testOne{
SEL mySelector=@selector(actionInvokeArgumentOne:argTwo:);
//1:方法签名类:使用NSObject的instance mehtod(也可以使用Class mehtod), 先取得一個NSMethodSignature对象, 並创建一個NSInvocation.被调用的消息actionInvokeArgumentOne:argTwo:.
NSMethodSignature *signature=[self methodSignatureForSelector:mySelector];
NSInvocation *invocation=[NSInvocation invocationWithMethodSignature:signature];
//2:這时取得的invocation只有简单的method可帶入的argument數量, 在正式調用之前你還需要設定target跟selector.
[invocation setTarget:self];
[invocation setSelector:mySelector];
//3设置参数
NSInteger argOne = 10;
NSNumber *argTwo = @20;
/*
第一个参数:需要给指定方法传递的值,第一个参数需要接收一个指针,也就是传递值的时候需要传递地址
第二个参数:需要给指定方法的第几个参数传值
*/
[invocation setArgument:&argOne atIndex:2];
[invocation setArgument:&argTwo atIndex:3];
//4:消息调用
[invocation invoke];
/*
注意点:
1:NSInvocation的使用有一個地方要特別注意, invocation不能使用 alloc跟init來建立对象, 只能使用invocationWithMethodSignature:來建立对象.
2:使用Invocation, method所帶入的参數也不用都转成object, int、BOOL都可以使用.
3:NSMethodSignature的numberOfArguments最小值是2; 0跟1是給预设的隱藏参數使用(self & _cmd).
*/
}
-(void)actionInvokeArgumentOne:(NSInteger)argOne argTwo:(NSNumber *)argTwo{
NSLog(@"action: arg1 + arg2= %d", argOne + [argTwo integerValue]);
// NSInvocation[10080:1915122] action: arg1 + arg2=30
}
/**
* 2:自定义类的使用
*/
-(void)testTwo{
SHClass *class=[[SHClass alloc]init];
NSString *myString = @"My string";
//普通调用
NSString *normalInvokeString=[class appendMyString:myString];
NSLog(@"The normal invoke string is: %@", normalInvokeString);
//NSInvocation调用
SEL mySelector = @selector(appendMyString:);
NSMethodSignature * sig = [[SHClass class]
instanceMethodSignatureForSelector: mySelector];
NSInvocation * myInvocation = [NSInvocation invocationWithMethodSignature: sig];
[myInvocation setTarget: class];
[myInvocation setSelector: mySelector];
[myInvocation setArgument: &myString atIndex: 2];
NSString * result = nil;
[myInvocation retainArguments];
[myInvocation invoke];
[myInvocation getReturnValue: &result];
NSLog(@"The NSInvocation invoke string is: %@", result);
// The NSInvocation invoke string is: My string after append method
}
#import <Foundation/Foundation.h>
@interface SHClass : NSObject
-(NSString *)appendMyString:(NSString *)string;
@end
#import "SHClass.h"
@implementation SHClass
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
}
return self;
}
-(NSString *)appendMyString:(NSString *)string
{
NSString *mString = [NSString stringWithFormat:@"%@ after append method", string];
// The normal invoke string is: My string after append method
return mString;
}
@end