学计算机的那个

不是我觉到、悟到,你给不了我,给了也拿不住;只有我觉到、悟到,才有可能做到,能做到的才是我的.

0%

NSInvocation

消息发送

在iOS中不通过类可以直接调用某个对象的消息方式有两种:

  1. performSelector:withObject;
  2. NSInvocation

performSelector使用

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:&para atIndex:2];

触发,就可以发送一条消息

1
[invocatin invoke];

下面是调用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:&para atIndex:2];
[invocatin invoke];

组件化路由跳转(Mediator)

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];

//消息发送的参数,签名两个是class和selector,所以方法参数从第3个开始
[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;
}

参考

  1. Runtime应用(三):NSInvocation