iOS开发 - performSelector:传递两个以上参数传、递结构体

▶ 如何传递两个以上的参数

下面用三种方式实现

DemoA:将所有参数放入一个字典或数组传过去!这种方式需要改动要调用方法的取参数的方式,比如使用字典传值时,双方需约定每一个参数放入字典对应的 key 是什么

复制代码
- (void)viewDidLoad {
    [super viewDidLoad];

    NSDictionary *paramDic = @{@"param1":@"string",@"param2":@[@2,@3,@3],@"param3":@123};
    [self performSelector:@selector(testFunctionWithParams:) withObject:paramDic];
}

- (void)testFunctionWithParams:(NSDictionary *)paramDic {
    NSLog(@"%s dic:%@",__FUNCTION__, paramDic);
}
复制代码

DemoB:使用 objc_msgSend() 。利用这种方法可以传递多个参数的特性调用方法执行

复制代码
- (void)viewDidLoad {
    [super viewDidLoad];
    // 需要引入头文件  #import <objc/message.h>
    ((void (*)(id,SEL,NSString *, NSArray *, NSInteger))objc_msgSend)(self, @selector(textFunctionWithParam:param2:param3:),@"111",@[@2,@3],123);
}

-(void)textFunctionWithParam:(NSString *)param1 param2:(NSArray *)param2 param3:(NSInteger)param3 {
    NSLog(@"param1:%@, param2:%@, param3:%ld",param1, param2, param3);
}
复制代码

DemoC:使用 NSInvocation

复制代码
 1 #import "ViewController.h"
 2 @implementation ViewController
 3 
 4 - (void)viewDidLoad {
 5     [super viewDidLoad];
 6     
 7     NSArray *paramArray = [NSArray arrayWithObjects:@"hello", @[@222,@333],@122,nil];
 8     [self performSelector:@selector(textFunctionWithParam:param2:param3:) withObjects:paramArray];
 9 }
10 
11 - (id)performSelector:(SEL)selector withObjects:(NSArray *)objects{
12     
13     // 方法签名
14     NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector];
15     
16     if (signature == nil) {
17         // 可以抛出异常也可以不操作
18     }
19     
20     // 通过 NSInvocation对象 包装一次方法调用:方法调用者、方法名、方法参数、方法返回值
21     NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];// 可以使用方法的签名来创建一个 NSInvocation对象
22     invocation.target = self;
23     invocation.selector = selector;
24     
25     // NSMethodSignature 有两个常用的只读属性
26     // numberOfArguments   方法参数的个数
27     // methodReturnLength  方法返回值类型的长度,大于 0 表示有返回值
28     NSInteger paramsCount = signature.numberOfArguments - 2; // 除self、_cmd 以外的参数个数
29     paramsCount = MIN(paramsCount, objects.count);
30     
31     // 参数
32     for (NSInteger i = 0; i < paramsCount; i++) {
33         id object = objects[i];
34         if ([object isKindOfClass:[NSNull class]]) continue;
35         
36         // 设置参数时必须传递参数的地址
37         // 参数赋值:注意下标从 2 开始,因为 0、1 已经被 target 与 selector 占用
38         [invocation setArgument:&object atIndex:i + 2];
39     }
40     
41     // 调用方法:有返回值类型,才去获得返回值
42     [invocation invoke];
43     
44     // 获取返回值
45     id returnValue = nil;
46     if (signature.methodReturnLength) {
47         // 返回值与设置参数一样,都必须将地址传过去
48         [invocation getReturnValue:&returnValue];
49     }
50     return returnValue;
51 }
52 
53 // 调用的方法
54 -(void)textFunctionWithParam:(NSString *)param1 param2:(NSArray *)param2 param3:(NSString*)param3 {
55     
56     NSLog(@"param1:%@, param2:%@, param3:%d",param1, param2, [param3 intValue]);
57 }
58 
59 @end
复制代码

▶ 传递结构体

我们知道 NSNumber 是 NSValue 的子类,但 NSNumber 只能包装数字类型,而 NSValue 可以包装任意值

因此可以用 NSValue 将结构体包装后加入 NSArray或NSDictionary 中,代码如下

复制代码
#import "ViewController.h"
typedef struct MakeStruct{
    int x;
    int y;
}testStruct;

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 结构体
    testStruct testS = {101, 192};
    NSValue *valueStruct = [NSValue valueWithBytes:&testS objCType:@encode(testStruct)];
    
    NSDictionary *dataDic = @{@"param1":@"ssfs",@"param2":@[@333,@32343],@"param3":valueStruct};
    [self performSelector:@selector(testFunctionWithParams:) withObject:dataDic];
}

- (void)testFunctionWithParams:(NSDictionary *)paramDic {
    NSValue *paramValue = paramDic[@"param3"];
    testStruct paramStruct;
    [paramValue getValue:&paramStruct];
    NSLog(@"取出结构体中的 x 值:%d",paramStruct.x);
}

@end
复制代码

 

posted on   低头捡石頭  阅读(350)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
历史上的今天:
2018-03-22 iOS第三方 - AFNetworking_2.0版 02:如何使用
2018-03-22 iOS第三方 - AFNetworking_2.0版 01:原理
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示