美文网首页
3-2 runtime-消息传递机制

3-2 runtime-消息传递机制

作者: Rumbles | 来源:发表于2019-03-28 17:16 被阅读0次

经典错误:unrecognized selector sent to instance 0x60400000e3e0。

程序崩溃很容易理解,因为在第一步查找方法中,在自己的类对象以及父类的类对象中都没有找到这个方法,所以转向动态方法解析,动态方法解析我们什么也没做,所以会转向消息转发,消息转发我们也什么都没做,所以最后产生崩溃。接下来我们实现一下动态方法解析。

方法发送流程

1.判断receiver 是否为空 
2.不为空从 receiverClass 的cache 里面查找
3.没有 从receiverClass的方法列表查找
4.没有 从父类的 cache  里面查找
5.没有 从receiverClass 父类 的方法列表查找
6.一直找 直到没有父类
7.都没有那么就会走方法解析

方法解析

是对象方法时,调用 resolveInstanceMethod:方法
当调用的是类方法时,调用resolveClassMethod:方法

/////> 第一次纠错 动态方法解析
+ (BOOL)resolveInstanceMethod:(SEL)sel{
    if (sel == @selector(studentTest)) {
        Method method = class_getInstanceMethod(self, @selector(test2));
        class_addMethod(self, sel, method_getImplementation(method), "v16@0:8");
        return YES;
    }
    
    return [super resolveInstanceMethod:sel];
}

- (void)test2 {
    NSLog(@"test2");
}

消息转发 消息转发通俗地讲就是本类没有能力去处理这个消息,那么就转发给其他的类,让其他类去处理

///> 第二次纠错 消息转发。转发给其他类实现
- (id)forwardingTargetForSelector:(SEL)aSelector {
    Car *car = Car.new;
    if ([car respondsToSelector:aSelector]) {
        return car;
    }
    return nil;
}







///> 第三次纠错
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{    
    if(aSelector == @selector(messageForwardingtestAge:)){
        return [NSMethodSignature signatureWithObjCTypes:"v20@0:8i16"];
    }
    return [super methodSignatureForSelector:aSelector];
}

//NSInvocation封装了一个方法调用,包括:方法调用者,方法名,方法参数
//@  anInvocation.target 方法调用者
//@   anInvocation.selector 方法名
//@   [anInvocation getArgument:NULL atIndex:0];
- (void)forwardInvocation:(NSInvocation *)anInvocation{
    NSLog(@"%@ %@", anInvocation.target, NSStringFromSelector(anInvocation.selector));
    int age;
    [anInvocation getArgument:&age atIndex:2];
    NSLog(@"messageForwarding1 %d", age);
    //这行代码是把方法的调用者改变为student对象
    // [anInvocation invokeWithTarget:[[Student alloc] init]];
}

为什么有三个函数

在第三阶段消息转发阶段为什么会有三个函数这个复杂?如果我们想要转发消息,那么直接在- (id)forwardingTargetForSelector:(SEL)aSelector去返回一个消息转发对象就可以了呀。设计三个函数的好处就是,当来到- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector这个方法时,如果这个方法返回为空,那么走到这里直接结束方法调用,产生崩溃,而如果返回不为空,那么就会继续去调用- (void)forwardInvocation:(NSInvocation *)anInvocation这个方法,那么来到这个里面,我们就可以为所欲为,即使我们什么也不做,运行程序也不会崩溃了,我们可以在这个方法里面为方法指定新的调用者,也即是进行消息转发,也可以做一些其他的操作,都可以,这就是这样设计的一个好处,我们可以在这个方法里面做一切我们想做的

相关文章

  • 3-2 runtime-消息传递机制

    经典错误:unrecognized selector sent to instance 0x60400000e3e...

  • Runtime-(三)消息传递机制

    我们知道在OC中,所有的方法调用最终都会转换成objc_msgSend形式的方法调用。如下图: 而对于调用父类的方...

  • Runtime-消息传递的流程机制

    缓存查找流程 根据给定的方法选择器SEL,来查找bucket_t中具体的方法实现IMP bucket_t是方法缓存...

  • runtime-消息传递与转发机制

    参考文章:继承自NSObject的不常用又很有用的函数【重点推荐】Objective-C Runtime 1小时入...

  • 底层技术以及runtime分享

    https://minilv.github.io/2019/03/17/Runtime-消息机制土味讲解/?nsu...

  • Runtime-消息机制

    Objective-C是一门动态语言,类型的判断、类的成员变量、方法的内存地址都是在程序的运行阶段才最终确定,并且...

  • runtime-消息机制

    从异常说起 我们都知道,在iOS中存在这么一个通用类类型id,它可以用来表示任何对象的类型 —— 这意味着我们使用...

  • runtime-消息机制

    OC方法调用,其实都是转换为objc_msgSend函数调用objc_msgSend的执行流程可以分为3大阶段:消...

  • Runtime-原理

    runtime初探对象与方法的本质runtime-消息发送runtime-动态方法解析runtime-消息转发 r...

  • iOS开发-runtime-消息传递和转发机制

    objective-c是一门动态语言,动态语言的特点就是方法的调用是在运行时(runtime)而不是编译时。 C语...

网友评论

      本文标题:3-2 runtime-消息传递机制

      本文链接:https://www.haomeiwen.com/subject/nepbvqtx.html