iOS筆記 - performSelector如何傳遞兩個以上引數、如何傳遞結構體
阿新 • • 發佈:2022-03-22
如何傳遞兩個以上引數
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:¶mStruct]; 27 NSLog(@"取出結構體中的 x 值:%d",paramStruct.x); 28 29 } 30 31 @end