消息发送 在iOS中不通过类可以直接调用某个对象的消息方式有两种:
performSelector:withObject
;
NSInvocation
1 2 3 4 5 6 7 8 @implementation HTOtherModule - (void )doSomethingWithParameter:(NSString *)para{ NSLog (@"done some with:%@" ,para); } @end
1 2 3 Class cls = NSClassFromString (@"HTOtherModule" ); id obj = [[cls alloc]init];[obj performSelector:NSSelectorFromString (@"doSomethingWithParameter:" ) withObject:@"this is the value" ];
performSelector虽然能达到调用方法的目的,但是传递的参数最多只能有两个,也许可以通过封装进字典来传递,但是这样就徒增了工作。我们可以用NSInvocation的特性来达到这个目的。
NSInvocation NSInvocation与其他NSObject类不一样,不会通过alloc/init来生成,它需要通过一个方法签名NSMethodSignature来生成
1 NSInvocation *invocatin = [NSInvocation invocationWithMethodSignature:sig];
而NSMethodSignature由类的selector来形成的
1 NSMethodSignature *sig = [cls instanceMethodSignatureForSelector:aSelecotor];
依次填补参数,
1 2 3 4 [invocatin setTarget:obj]; [invocatin setSelector:aSelecotor]; NSString *para = @"this is the value" ;[invocatin setArgument:¶ atIndex:2 ];
触发,就可以发送一条消息
下面是调用HTOtherModule类的方法的完整代码:
1 2 3 4 5 6 7 8 9 10 SEL aSelecotor = NSSelectorFromString (@"doSomethingWithParameter:" ); Class cls = NSClassFromString (@"HTOtherModule" ); id obj = [[cls alloc]init]; NSMethodSignature * sig = [cls instanceMethodSignatureForSelector:aSelecotor]; NSInvocation * invocatin = [NSInvocation invocationWithMethodSignature:sig]; [invocatin setTarget:obj]; [invocatin setSelector:aSelecotor]; NSString *para = @"this is the value" ; [invocatin setArgument:¶ atIndex:2 ]; [invocatin invoke];
Category
1 2 3 4 5 @interface HTMediator (HTOtherModule )- (NSString *)otherModulePerform:(NSString *)targetName action:(NSString *)actionName name:(NSString *)name hour:(NSUInteger )hour place:(NSString *)palce doSomething:(NSString *)doSomething; @end
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 32 - (id )performTarget:(NSString *)targetName action:(NSString *)actionName parameters:(NSArray *)parameters{ Class tagetClass = NSClassFromString (targetName); NSObject *tagert= [[tagetClass alloc]init]; SEL aSelector = NSSelectorFromString (actionName); NSMethodSignature *methodSignature = [tagetClass instanceMethodSignatureForSelector:aSelector]; if (methodSignature == nil ) { NSLog (@"找不到这个方法" ); return nil ; } else { NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; [invocation setTarget:tagert]; [invocation setSelector:aSelector]; [parameters enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { [invocation setArgument:&obj atIndex:idx+2 ]; }]; [invocation invoke]; __autoreleasing id callBackObject = nil ; if (methodSignature.methodReturnLength) { [invocation getReturnValue:&callBackObject]; } return callBackObject; } return nil ; }
参考
Runtime应用(三):NSInvocation