iOS 消息转发机制

在iOS中,如果遇到消息无法处理。(例如在头文件中声明了该方法,但是在m文件中没有实现该方法).对方法发生调用后,系统会依照从当前类、当前类的父类、父类的父类...这个顺序进行查找这个方法,如果递归直至根类都没能处理这个方法。在系统发生cash之前,会先启动消息转发机制。试图对该消息进行处理。

动态方法解析

+ (BOOL)resolveInstanceMethod:(SEL)sel;

在本类内部寻找选择子sel 的方法;

+ (BOOL)resolveInstanceMethod:(SEL)sel{
    if (sel == @selector(eat)) {
            class_addMethod(self, sel, (IMP)eatMeat, "v@:@:");
            return YES;
        }
    return [super resolveInstanceMethod:sel];
}-(BOOL)resolveInstanceMethod:(SEL)sel{
    if (sel == @selector(eat)) {
            class_addMethod(self, sel, (IMP)eatMeat, "v@:@:");
            return YES;
        }
    return [super resolveInstanceMethod:sel];
}


用这个方法的前提是本类内部已经实现了eatMeat方法。如果eatMeat依然不存在,则会进入 备援接受者寻找处理方法。

 

 

备援接收者(快速消息转发)

 

 

如果本类动态方法解析无法处理则可以把处理方法交给其他接受者。在forwordingTargetForSelector方法中重新初始化一个类,并该类中调用该方法,前提是该类中有这个方法。如果处理不了,会向父类去寻找该方法,直到NSObject。如果备援接受者确定处理不了该方法,将会进入完整的消息转发。

 

- (id)forwordingTargetForSelector:(SEL)aSelector;

- (id)forwardingTargetForSelector:(SEL)aSelector{
    NSString *selectorStr = NSStringFromSelector(aSelector);//获取消息的选择子
    if ([selectorStr isEqualToString:@"eat"]) {
        AnimalForwardingTarget *action = [AnimalForwardingTarget new];
        return action;
    }
    return [super forwardingTargetForSelector:aSelector]; 
}id)forwardingTargetForSelector:(SEL)aSelector{
    NSString *selectorStr = NSStringFromSelector(aSelector);//获取消息的选择子
    if ([selectorStr isEqualToString:@"eat"]) {
        AnimalForwardingTarget *action = [AnimalForwardingTarget new];
        return action;
    }
    return [super forwardingTargetForSelector:aSelector]; 
}

完整的消息转发

生成方法签名

- (NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector;

- (NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector{
    NSString *selectedStr = NSStringFromSelector(aSelector); //获取消息的选择子
    if ([selectedStr isEqualToString:@"eat"]) {
        NSMethodSignature *sign = [NSMethodSignature signatureWithObjCTypes:"v@:@"];
        return sign;
    }
    return [super methodSignatureForSelector:aSelector];
}NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector{
    NSString *selectedStr = NSStringFromSelector(aSelector); //获取消息的选择子
    if ([selectedStr isEqualToString:@"eat"]) {
        NSMethodSignature *sign = [NSMethodSignature signatureWithObjCTypes:"v@:@"];
        return sign;
    }
    return [super methodSignatureForSelector:aSelector];
}

利用签名生成NSInnovation

- (void)forwardInvocation:(NSInvocation *)anInvocation{
    NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:"v@:@"]; //利用签名生成NSInnovation
    anInvocation = [NSInvocation invocationWithMethodSignature: signature];
    [anInvocation setTarget: self];
    anInvocation.selector = NSSelectorFromString(@"eatDogFood");
    AnimalForwardInvocation* animalInvocation = [AnimalForwardInvocation new];
    if ([animalInvocation respondsToSelector:[anInvocation selector]]) {     //如果AnimalForwardInvovation这个类中实现了选择子eatDogFood
        [anInvocation invokeWithTarget: animalInvocation];                    
    } else {
        [super forwardInvocation: anInvocation];
    }
}void)forwardInvocation:(NSInvocation *)anInvocation{
    NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:"v@:@"]; //利用签名生成NSInnovation
    anInvocation = [NSInvocation invocationWithMethodSignature: signature];
    [anInvocation setTarget: self];
    anInvocation.selector = NSSelectorFromString(@"eatDogFood");
    AnimalForwardInvocation* animalInvocation = [AnimalForwardInvocation new];
    if ([animalInvocation respondsToSelector:[anInvocation selector]]) {     //如果AnimalForwardInvovation这个类中实现了选择子eatDogFood
        [anInvocation invokeWithTarget: animalInvocation];                    
    } else {
        [super forwardInvocation: anInvocation];
    }
}

如果连完整的消息转发也处理不了该方法,系统会发生cash.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值