一.概述
在iOS中我們直接調(diào)某個(gè)對(duì)象的消息的方式有2種
-
系統(tǒng)NSObject類型中提供了2個(gè)方法
// 一個(gè)參數(shù)
[self performSelector:<#(SEL)#> withObject:<#(id)#>];
// 兩個(gè)參數(shù)
[self performSelector:<#(SEL)#> withObject:<#(id)#> withObject:<#(id)#>];
- 使用NSInvocation.
### 二. NSInvocation的使用
```objc
- (void)viewDidLoad {
[super viewDidLoad];
//方法
SEL selector = @selector(run);
//初始化方法簽名(方法的描述)
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector];
// NSInvocation : 利用一個(gè)NSInvocation對(duì)象包裝一次方法調(diào)用(方法調(diào)用者莱没、方法名辜王、方法參數(shù)姚淆、方法返回值)
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
//設(shè)置調(diào)用者
invocation.target = self;
//設(shè)置調(diào)用方法
invocation.selector = selector;
//設(shè)置參數(shù)
NSUInteger object = 5;
//參數(shù)從2開始于样,index為0表示target,1為_cmd
[invocation setArgument:&object atIndex:2];
//調(diào)用方法
[invocation invoke];
}
-(void)run:(NSInteger)num{
NSLog(@"run");
}
三. NSInvocation實(shí)現(xiàn)多參數(shù)的封裝
系統(tǒng)的NSObject提供的performSelector的方法只提供了最多兩個(gè)參數(shù)的調(diào)用,我們可以使用NSInvocation封裝一個(gè)多個(gè)參數(shù)的performSelector方法.
#import <Foundation/Foundation.h>
@interface NSObject (MutiPerform)
-(id)performSelector:(SEL)Selector withObjects:(NSArray *)objects;
@end
#import "NSObject+MutiPerform.h"
@implementation NSObject (MutiPerform)
-(id)performSelector:(SEL)selector withObjects:(NSArray *)objects{
//初始化方法簽名
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector];
// 如果方法selector不存在
if(signature == nil){
// 拋出異常
NSString *reason = [NSString stringWithFormat:@"%@方法不存在",NSStringFromSelector(selector)];
@throw [NSException exceptionWithName:@"error" reason:reason userInfo:nil];
}
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.target = self;
invocation.selector = selector;
//參數(shù)個(gè)數(shù)signature.numberOfArguments 默認(rèn)有一個(gè)_cmd 一個(gè)target 所以要-2
NSInteger paramsCount = signature.numberOfArguments - 2;
// 當(dāng)objects的個(gè)數(shù)多于函數(shù)的參數(shù)的時(shí)候,取前面的參數(shù)
//當(dāng)當(dāng)objects的個(gè)數(shù)少于函數(shù)的參數(shù)的時(shí)候,不需要設(shè)置,默認(rèn)為nil
paramsCount = MIN(paramsCount, objects.count);
for (NSInteger index = 0; index < paramsCount; index++) {
id object = objects[index];
// 對(duì)參數(shù)是nil的處理
if([object isKindOfClass:[NSNull class]]) continue;
[invocation setArgument:&object atIndex:index+2];
}
//調(diào)用方法
[invocation invoke];
// 獲取返回值
id returnValue = nil;
//signature.methodReturnLength == 0 說(shuō)明給方法沒有返回值
if (signature.methodReturnLength) {
//獲取返回值
[invocation getReturnValue:&returnValue];
}
return returnValue;
}