iOS runtime随笔-消息转发机制

运行时的消息转发分三步, 当你调用了没有实现的方法时, 有机会通过runtime的消息转发机制补救一下

  1. resolveInstanceMethod/resolveClassMethod 这里可以动态去创建方法来解决Crash
  2. forwardingTargetForSelector ​​​​​第一步未解决, 就会走到这里, 可以给出一个Target去转发这个消息(方法调用)
  3. forwardInvocation ​​​​​​​上面2步都没有解决问题, 这里是最后一次机会, 利用methodSignatureForSelector返回一个方法签名, 在forwardInvocation中转发给对应的target

实例方法实现参考

+ (BOOL)resolveInstanceMethod:(SEL)sel {
    if (sel == @selector(testInstance)) {
        IMP imp = class_getMethodImplementation([self class], @selector(test));
        return class_addMethod([self class], sel, imp, "v@:");
    }
    return NO;
}

- (id)forwardingTargetForSelector:(SEL)aSelector {
    if (aSelector == @selector(testInstance)) {
        return self.realObj;
    }
    return [super forwardingTargetForSelector:aSelector];
}


- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    if (aSelector == @selector(testInstance)) {
        return [[RealTestObject alloc] methodSignatureForSelector:aSelector];
    }
    return [super methodSignatureForSelector: aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation {
    SEL sel = anInvocation.selector;
    if ([self.realObj respondsToSelector:sel]) {
        [anInvocation invokeWithTarget:self.realObj];
        return;
    }
    [super forwardInvocation:anInvocation];
}

类方法实现参考

+ (BOOL)resolveClassMethod:(SEL)sel {
    if (sel == @selector(testClass)) {
//也可以通过block创建一个IMP去替代方法实现
//        IMP imp = imp_implementationWithBlock(^(void) {
//            NSLog(@"imp_implementationWithBlock");
//        });
        IMP imp = class_getMethodImplementation(objc_getMetaClass("TestObject"), @selector(testLogClass));
        class_addMethod(objc_getMetaClass("TestObject"), sel, imp, "v@:");
        return YES;
    }
    return NO;
}

+ (id)forwardingTargetForSelector:(SEL)aSelector {
    if (aSelector == @selector(testClass)) {
        return [RealTestObject class];
    }
    return [super forwardingTargetForSelector:aSelector];
}

+ (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    if (aSelector == @selector(testClass)) {
        return [RealTestObject methodSignatureForSelector:aSelector];
    }
    return [super methodSignatureForSelector:aSelector];
}

+ (void)forwardInvocation:(NSInvocation *)anInvocation {
    SEL sel = anInvocation.selector;
    if (sel == @selector(testClass)) {
        [anInvocation invokeWithTarget:[RealTestObject class]];
        return;
    }
    [super forwardInvocation:anInvocation];
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值