iOS 开发继续加油

Runtime消息传递机制

2019-01-22  本文已影响73人  昵称是乱起的
先看下整个Class的底层结构
image.png

objc_msgSend的源码是汇编实现的

objc_msgSend的执行流程01-消息发送
image.png

如果是从class_rw_t中查找方法,已经排序的采用二分查找,没有排序的遍历查找
receiver通过isa指针找到receiverClass
receiverClass通过superclass指针找到superClass

objc_msgSend的执行流程02-动态方法解析
image.png

动态解析过后,会重新走“消息发送”的流程,“从receiverClass的cache中查找方法”这一步开始执行
开发者可以实现以下方法,来动态添加方法实现
+resolveInstanceMethod:
+resolveClassMethod:

#InstanceMethod第1种写法
- (void)other
{
    NSLog(@"%s",__func__);
}
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    if (sel == sel_registerName("test")) {
        Method method = class_getInstanceMethod(self, sel_registerName("test"));
        class_addMethod(self, sel, method_getImplementation(method), method_getTypeEncoding(method));
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}
#InstanceMethod第2种写法
void c_other(id self, SEL _cmd)
{
    NSLog(@"c_other - %@ - %@", self, NSStringFromSelector(_cmd));
}
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    if (sel == @selector(test)) {
        class_addMethod(self, sel, (IMP)c_other, "v16@0:8");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}
#InstanceMethod第3种写法
struct method_t {
    SEL sel;
    char *types;
    IMP imp;
};
- (void)other
{
    NSLog(@"%s",__func__);
}
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    if (sel == @selector(test)) {
        struct method_t *method = (struct method_t *)class_getInstanceMethod(self, @selector(other));
        class_addMethod(self, sel, method->imp, method->types);
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}
#ClassMethod写法
void c_other(id self, SEL _cmd)
{
    NSLog(@"c_other - %@ - %@", self, NSStringFromSelector(_cmd));
}
+ (BOOL)resolveClassMethod:(SEL)sel
{
    if (sel == @selector(test)) {
        class_addMethod(object_getClass(self), sel, (IMP)c_other, "v16@0:8");
        return YES;
    }
    return [super resolveClassMethod:sel];
}

objc_msgSend的执行流程03-消息转发
image.png
+ (id)forwardingTargetForSelector:(SEL)aSelector
{
    if (aSelector == @selector(test)) return [[Person alloc] init];
    return [super forwardingTargetForSelector:aSelector];
}
//上面return NO才会来到这里
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    if (aSelector == @selector(test:)) {
        return [NSMethodSignature signatureWithObjCTypes:"i@:i"];
    }
    return [super methodSignatureForSelector:aSelector];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    [anInvocation invokeWithTarget:[[Person alloc] init]];
}

@dynamic value;// 提醒编译器不要自动生成setter和getter的实现、不要自动生成成员变量

super底层
 [self class];
 objc_msgSend(self, sel_registerName("class"))
 [super superclass];
 objc_msgSendSuper({self,class_getSuperclass(objc_getClass("Person"))}, sel_registerName("class")))
上一篇下一篇

猜你喜欢

热点阅读