當咱們有方法名和參數列表,想要動態地給對象發送消息,可用經過反射函數機制來實現,有兩種經常使用的作法:函數
1、performSelector測試
1 - (id)performSelector:(SEL)aSelector; 2 - (id)performSelector:(SEL)aSelector withObject:(id)object; 3 - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
經常使用的方法有這三個,其中aSelector能夠經過 NSSelectorFromString 方法拿到spa
SEL aSelector = NSSelectorFromString(selString);
可是 performSelector 的缺點是最多隻支持傳遞兩個參數.net
http://my.oschina.net/ososchina/blog/644117code
這篇文章給出的方法二說是能夠支持多參數,可是我嘗試了下未成功orm
2、NSInvocation對象
很少說,直接上栗子blog
// 測試反射函數 - (void)printWithString:(NSString *)string withNum:(NSNumber *)number withArray:(NSArray *)array { NSLog(@"%@, %@, %@", string, number, array[1]); } - (void)test { NSString *str = @"哈哈哈"; NSNumber *num = @20; NSArray *arr = @[@"ABC", @"DEF"]; // [self printWithString:str withNum:num withArray:arr]; SEL sel = NSSelectorFromString(@"printWithString:withNum:withArray:"); NSArray *objs = [NSArray arrayWithObjects:str, num, arr, nil]; [self performSelector:sel withObjects:objs]; } - (id)performSelector:(SEL)selector withObjects:(NSArray *)objects { // 方法簽名(方法的描述) NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector]; if (signature == nil) { //能夠拋出異常也能夠不操做。 } // NSInvocation : 利用一個NSInvocation對象包裝一次方法調用(方法調用者、方法名、方法參數、方法返回值) NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; invocation.target = self; invocation.selector = selector; // 設置參數 NSInteger paramsCount = signature.numberOfArguments - 2; // 除self、_cmd之外的參數個數 paramsCount = MIN(paramsCount, objects.count); for (NSInteger i = 0; i < paramsCount; i++) { id object = objects[i]; if ([object isKindOfClass:[NSNull class]]) continue; [invocation setArgument:&object atIndex:i + 2]; } // 調用方法 [invocation invoke]; // 獲取返回值 id returnValue = nil; if (signature.methodReturnLength) { // 有返回值類型,纔去得到返回值 [invocation getReturnValue:&returnValue]; } return returnValue; }
3、objc_msgSendget
objc_msgSend的寫法要複雜一點,具體能夠參看這篇文章,講的很清楚cmd
http://www.jianshu.com/p/efeb33712445
可是有個缺點是,須要指定好傳遞參數的類型,是否是能夠直接都用id呢?
經測試id可用
// objc_msgSend SEL sel = NSSelectorFromString(@"printWithString:withNum:withArray:"); ((void (*) (id, SEL, NSString *, NSNumber *, NSArray *)) objc_msgSend) (self, sel, str, num, arr);