1. 程式人生 > 其它 >iOS筆記 - performSelector如何傳遞兩個以上引數、如何傳遞結構體

iOS筆記 - performSelector如何傳遞兩個以上引數、如何傳遞結構體

如何傳遞兩個以上引數

1 - 傳遞兩個以上的引數有四種方式可以實現

① 將所有引數放入一個字典或陣列傳過去

注:這種方式需要改動要呼叫的方法的取引數的方式,比如使用字典傳值,雙方需約定每一個引數放入字典對應的 key 是什麼

 1 - (void)viewDidLoad {
 2     [super viewDidLoad];
 3     self.view.backgroundColor = [UIColor grayColor];
 4 
 5     NSDictionary *dic = @{@"param1":@"string",@"param2":@[@2,@3,@3],@"
param3":@123}; 6 [self performSelector:@selector(testFunctionWithParams:) withObject:dic]; 7 } 8 9 - (void)testFunctionWithParams:(NSDictionary *)paramDic { 10 NSLog(@"%s dic:%@",__FUNCTION__, paramDic); 11 }

② 使用 objc_msgSend() 傳遞:利用這種方法可以傳遞多個引數的特性呼叫方法執行

 1 - (void)viewDidLoad {
 2     [super viewDidLoad];
3 4 ((void (*)(id,SEL,NSString *, NSArray *, NSInteger))objc_msgSend)(self, @selector(textFunctionWithParam:param2:param3:),@"111",@[@2,@3],123); 5 6 } 7 8 -(void)textFunctionWithParam:(NSString *)param1 param2:(NSArray *)param2 param3:(NSInteger)param3 { 9 NSLog(@"param1:%@, param2:%@, param3:%ld
",param1, param2, param3); 10 }

③ 用 NSInvocation 傳遞:將方法採用 NSInvocation 呼叫,使其不限制引數數量

 1 - (void)viewDidLoad {
 2     [super viewDidLoad];
 3 
 4     NSArray *paramArray = [NSArray arrayWithObjects:@"hello", @[@222,@333],@122,nil];
 5     [self performSelector:@selector(textFunctionWithParam:param2:param3:) withObjects:paramArray];
 6 
 7 }
 8 
 9 // NSInvocation
10 - (id)performSelector:(SEL)selector withObjects:(NSArray *)objects{
11     
12     // 方法簽名
13     NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector];
14     if (signature == nil) {
15         
16         // 可以丟擲異常也可以不操作
17     }
18     
19     // NSInvocation : 利用一個 NSInvocation 物件包裝一次方法呼叫(方法呼叫者、方法名、方法引數、方法返回值)
20     NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
21     invocation.target = self;
22     invocation.selector = selector;
23     
24     // 設定引數
25     NSInteger paramsCount = signature.numberOfArguments - 2; // 除self、_cmd以外的引數個數
26     paramsCount = MIN(paramsCount, objects.count);
27     for (NSInteger i = 0; i < paramsCount; i++) {
28         id object = objects[i];
29         if ([object isKindOfClass:[NSNull class]]) continue;
30         [invocation setArgument:&object atIndex:i + 2];
31     }
32     
33     // 呼叫方法:有返回值型別,才去獲得返回值
34     [invocation invoke];
35     
36     // 獲取返回值
37     id returnValue = nil;
38     if (signature.methodReturnLength) {
39         [invocation getReturnValue:&returnValue];
40     }
41     
42     return returnValue;
43 }
44 
45 // 呼叫的方法
46 -(void)textFunctionWithParam:(NSString *)param1 param2:(NSArray *)param2 param3:(NSString*)param3 {
47     
48     NSLog(@"param1:%@, param2:%@, param3:%d",param1, param2, [param3 intValue]);
49 }

④ 利用 runtime 特性傳遞

如何傳遞結構體

1 - 程式碼示例

 1 #import "ViewController.h"
 2 typedef struct MakeStruct{
 3     
 4     int x;
 5     int y;
 6     
 7 }testStruct;
 8 @implementation ViewController
 9 
10 - (void)viewDidLoad {
11     [super viewDidLoad];
12 
13     // 傳結構體
14     testStruct testS = {101, 192};
15     NSValue *valueStruct = [NSValue valueWithBytes:&testS objCType:@encode(testStruct)];
16     
17     NSDictionary *dataDic = @{@"param1":@"ssfs",@"param2":@[@333,@32343],@"param3":valueStruct};
18     [self performSelector:@selector(testFunctionWithParams:) withObject:dataDic];
19 
20 }
21 
22 - (void)testFunctionWithParams:(NSDictionary *)paramDic {
23 
24    NSValue *paramValue = paramDic[@"param3"];
25    testStruct paramStruct;
26    [paramValue getValue:&paramStruct];
27    NSLog(@"取出結構體中的 x 值:%d",paramStruct.x);
28    
29 }
30 
31 @end