Runtime(二)

objc_msgSend

包括以下三个步骤

  • 消息发送
  • 动态方法解析
  • 消息转发

消息发送

Runtime(二)_第1张图片
image.png

动态方法解析

struct objc_method_t{
    SEL name;
    char *types;
    IMP imp;
};

- (void)other{
    NSLog(@"%s",__func__);
}

+ (BOOL)resolveInstanceMethod:(SEL)sel{
    NSLog(@"被调用了%s",__func__);
    if (sel == @selector(test)) {
        struct objc_method_t  *otherMethod = (struct objc_method_t *)class_getInstanceMethod(self, @selector(other));
        class_addMethod(self, sel, otherMethod->imp, otherMethod->types);
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

消息转发


- (id)forwardingTargetForSelector:(SEL)aSelector{
    
    if (aSelector == @selector(test)) {
        //objc_msgSend(student,sel);
        return [[student alloc]init];
    }
    return [super forwardingTargetForSelector:aSelector];
}

如果forwardingTargetForSelector 没有处理则进入下面方法

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
  
    if (aSelector == @selector(test)) {
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }
    return [super methodSignatureForSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation{
    /*
     NSLog(@"abc");
    */
}

总结:
objc_msgSend实质上是像接收者发送一个selector消息,开始的时候会在缓存中查找,没找到则从类或者元类中的方法列表中查找,找到则将其缓存起来并调用,如果从类对象or元类对象中没找到则会去其父类中查找,如果到基类都没找到则进入动态方法解析resolveInstanceMethod 如果这步不做处理,则会进如消息转发阶段,forwardingTargetForSelector如果这步也不处理则会进入下一阶段methodSignatureForSelectormethodSignatureForSelector,如果这里也不进行处理,则会抛出异常unrecognized selector sent to instance.

Runtime(二)_第2张图片
image.png

你可能感兴趣的:(Runtime(二))