简介
Objective-C 是动态语言,所有的消息都是在 Runtime 进行派发的。
最底层的转发函数为objc_msgSend。
使用 performSelector 可以给对象发送消息,但是其有几个短板
- 在 ARC 场景下 performSelector 可能会造成内存泄漏
- performSelector 至多接收 2 个参数,如果参数多余 2 个,我们就无法使用 performSelector 来向对象发送消息了。
- performSelector 限制参数类型为 id,以标量数据(int double NSInteger 等)为参数的方法使用 performSelector 调用会出现各种各样诡异的问题
NSInvocation 是苹果工程师们提供的一个高层的消息转发系统。它是一个命令对象,是一个消息调用类,可以给任何 Objective-C 对象类型发送消息。
NSInvocation 包含了所有OC消息的成分:target、selector、参数、返回值等。NSInvocation可以将消息转换成一个对象,消息的每一个参数能够直接设定,而且当一个NSInvocation对象调度时返回值是可以自己设定的。一个NSInvocation对象能够重复的调度不同的目标(target),而且它的selector也能够设置为另外一个方法签名。
NSInvocation 的使用
使用步骤:
创建方法创建签名对象NSMethodSignature 根据签名对象创建调用NSInvocation 设置调用对象相关信息 调用方法 获取返回值 无参数、无返回值
无参数、无返回值 的 对应代码为:
- (void)startTest_Imple { // 获取方法签名 NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:@selector(startTest)]; // 生成调用对象 NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; // 设置target invocation.target = self; // 设置方法实现 invocation.selector = @selector(startTest); // 调用 [invocation invoke]; } - (void)startTest { NSLog(@"无参数、无返回值:startTest_1"); }
两个个参数、有返回值的代码为:
- (void)startTest_Imple_3 { // 获取方法签名 NSMethodSignature *signature = [ViewController instanceMethodSignatureForSelector:@selector(startTest_3:text1:)]; // 生成调用对象 NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; // 设置target invocation.target = self; // 设置方法实现 invocation.selector = @selector(startTest_3:text1:); // 设置参数,参数必须从2开始,第一个第二个参数为target和selector NSString *argument = @"参数1"; NSString *argument1 = @"参数2"; [invocation setArgument:&argument atIndex:2]; [invocation setArgument:&argument1 atIndex:3]; // 调用 [invocation invoke]; NSString *returnValue = nil; [invocation getReturnValue:&returnValue]; NSLog(@"返回值:%@",returnValue); } - (NSString *)startTest_3:(NSString *)text text1:(NSString *)text1 { NSLog(@"参数%@--%@,无返回值:startTest_1",text,text1); return @"返回值"; }
具体实例,下面用NSInvocation方式来调用sendMessageWithNumber方法。
- (void)viewDidLoad { [super viewDidLoad]; //NSInvocation;用来包装方法和对应的对象,它可以存储方法的名称,对应的对象,对应的参数, /* NSMethodSignature:签名:再创建NSMethodSignature的时候,必须传递一个签名对象,签名对象的作用:用于获取参数的个数和方法的返回值 */ //创建签名对象的时候不是使用NSMethodSignature这个类创建,而是方法属于谁就用谁来创建 NSMethodSignature*signature = [ViewController instanceMethodSignatureForSelector:@selector(sendMessageWithNumber:WithContent:)]; //1、创建NSInvocation对象 NSInvocation*invocation = [NSInvocation invocationWithMethodSignature:signature]; invocation.target = self; //invocation中的方法必须和签名中的方法一致。 invocation.selector = @selector(sendMessageWithNumber:WithContent:); /*第一个参数:需要给指定方法传递的值 第一个参数需要接收一个指针,也就是传递值的时候需要传递地址*/ //第二个参数:需要给指定方法的第几个参数传值 NSString*number = @"1111"; //注意:设置参数的索引时不能从0开始,因为0已经被self占用,1已经被_cmd占用 [invocation setArgument:&number atIndex:2]; NSString*number2 = @"啊啊啊"; [invocation setArgument:&number2 atIndex:3]; //2、调用NSInvocation对象的invoke方法 //只要调用invocation的invoke方法,就代表需要执行NSInvocation对象中制定对象的指定方法,并且传递指定的参数 [invocation invoke]; } - (void)sendMessageWithNumber:(NSString*)number WithContent:(NSString*)content{ NSLog(@"电话号%@,内容%@",number,content); }
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。