标签:
Invocation简单介绍
方法一:运行时方法:(这里在之前的文章定时器的几种方法中说过:www.cnblogs.com/iCocos/p/4694581.html)
1:创建一个签名:
NSMethodSignature *singature = [NSMethodSignature signatureWithObjCTypes:"v@:"];
这里我想如果你仔细的话肯定注意到了:后面的“v@:”,这里是运行时的语法
在这里是指一个方法
• v放回viod类型
• @一个id类型的对象
• :对应SEL
关于运行时这里不多介绍请查看笔者之前的文章,或者查看官方文档,这是一个iOS开发者必须会的知识点
2:通过前面创建一个请求,并且设置对应的target和SEL
NSInvocation *vocation = [NSInvocation invocationWithMethodSignature:singature]; vocation.target = self; vocation.selector = @selector(timeChange);
3:在讲请求传到NSTimer中去实现定时
[NSTimer scheduledTimerWithTimeInterval:1 invocation:vocation repeats:YES];
方法二:对应类直接创建
Signature签名: 在创建NSInvocation的时候, 必须传递一个签名对象
签名对象的作用 : 用于获取参数的个数和方法的返回值
注意点: 创建签名对象的时候不是使用NSMethodSignature类创建 \
一:而是方法属于谁就用谁来创建
NSMethodSignature *signature = [ViewController instanceMethodSignatureForSelector:@selector(sendMessageWithNumber:andContent:status:)];
// NSInvocation; 用来包装方法和对应的对象, 它可以存储方法的名称,对应的对象 ,对应的参数
二: .创建一个NSInvocation对象
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
三:设置对应的属性
invocation.target = self; // 保存方法所属的对象 // 给invocation设置的方法, 必须和签名中的方法一致 invocation.selector = @selector(sendMessageWithNumber:andContent:status:); // 保存方法名称
// 第一个参数: 需要给指定方法传递的值
// + 第一个参数需要接收一个指针, 也就是传递值的时候需要传递地址
// 第二个参数: 需要给指定方法的第几个参数传值
四:实现参数的设置
NSString *number = @"iCocos";
// 注意: 设置参数的索引时不能从0开始, 因为0已经被self占用, 1已经被_cmd占用
[invocation setArgument:&number atIndex:2];
// 2.调用NSInvocation对象的invoke方法
// 只要调用invocation的invoke方法, 就代表需要执行 \
五:NSInvocation对象中指定对象的指定方法, 并且传递指定的参数
[invocation invoke];
NSInvocation经典案例:多参数方法的封装:
1 - (id)performSelector:(SEL)aSelector withObjects:(NSArray *)objects 2 { 3 // 1.创建签名对象 4 NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:aSelector]; 5 6 // 判断传入的方法是否存储, 如果方法不存在签名对象为nil 7 if (signature == nil) { 8 // 传入的方法不存在 9 NSString *info = [NSString stringWithFormat:@" -[%@ %@]: unrecognized selector sent to instance", [self class], NSStringFromSelector(aSelector)]; 10 11 @throw [[NSException alloc] initWithName:@"一个牛B的错误" reason:info userInfo:nil]; 12 } 13 14 // 2.创建一个NSInvocation对象 15 NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; 16 17 // 3.保存方法所属的对象 18 invocation.target = self; 19 20 // 给invocation设置的方法, 必须和签名中的方法一致 21 // 4.保存方法名称 22 invocation.selector = aSelector; 23 24 // 5.设置参数 25 /* 26 当前如果直接遍历参数数组来设置参数, 会存在问题 27 如果参数数组元素多余参数个数, 那么就会报错 28 */ 29 NSUInteger arguments = signature.numberOfArguments - 2; 30 /* 31 如果直接遍历参数值的个数, 会存在问题 32 如果参数的个数大于了参数值的个数, 那么数组会越界 33 */ 34 NSUInteger objectsCount = objects.count; 35 /* 36 参数和参数值, 谁少就遍历谁 37 */ 38 NSUInteger count = MIN(arguments, objectsCount); 39 40 for (int i = 0; i < count; i++) { 41 NSObject *obj = objects[i]; 42 // 处理数组参数中NSNull问题 43 if ([obj isKindOfClass:[NSNull class]]) { 44 obj = nil; 45 } 46 [invocation setArgument:&obj atIndex:i + 2]; 47 } 48 49 // 6.调用NSInvocation对象的invoke方法 50 [invocation invoke]; 51 52 id res = nil; 53 // 判断当前方法是否有返回值 54 // NSLog(@"ReturnType = %zd", signature.methodReturnLength); 55 if ( signature.methodReturnLength != 0) { 56 // 7.获取返回值 57 // getReturnValue方法会将会去到的方法返回值赋值给传入的对象 58 [invocation getReturnValue:&res]; 59 } 60 61 return res; 62 }
以后我们有再多的参数都不用担心了,而且实现了各种优化,在上一篇我们使用JS调用OC的时候就没有这么麻烦了,直接传递一个参数(数组)进来就可以根据参数和对应的方法去实现相应的功
iOS开发——实用技术OC篇&?Invocation简单介绍
标签:
原文地址:http://www.cnblogs.com/iCocos/p/4758410.html