OC底层原理

[self class] 和 [super class]

2020-02-11  本文已影响0人  只写Bug程序猿
问题抛出

[self class][super class]结果是否一样呢

- (instancetype)init{
    self = [super init];
    if (self) {
        NSLog(@"%@",NSStringFromClass([self class]));
        NSLog(@"%@",NSStringFromClass([super class]));
//打印结果都为`Student`
    }
}
[self class]

class方法是什么

- (Class)class {
    return object_getClass(self);
}
///
Class object_getClass(id obj)
{
    if (obj) return obj->getIsa();
    else return Nil;
}

最终渠道的objisa.
首先来看[self class]因为这里objstudent对象,所以这里打印Student为当前类.

[super class]
方法1 汇编

前边[self class],调用 class方法的为 self对象,那么super是个什么呢?
我们不妨 Debug Workflow -> always show disassembly看汇编.
方法的调用说白了就是消息的发送过程.那么汇编有没有类似objc_mesSend呢,发现[super class]其实是调用了objc_msgSendSuper

OBJC_EXPORT void
objc_msgSendSuper(void /* struct objc_super *super, SEL op, ... */ )
    OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0);

第一个参数为一个objc_super的结构体

struct objc_super {
    __unsafe_unretained _Nonnull id receiver;
    __unsafe_unretained _Nonnull Class super_class;
};

那么[super class]就等价于

struct objc_super lg_super = {
//我们这里研究对象为当前对象所以消息接收这位self
   self,
   class_getSuperclass([self class]),
};
objc_msgSendSuper(&lg_super,@selector(class))

打印结果依然为Student

方法2 hook
@implementation NSObject (JS)

+ (void)load{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
         [JSRuntimeTool js_bestMethodSwizzlingWithClass:self oriSEL:@selector(class) swizzledSEL:@selector(js_class)];
    });
}

- (Class)js_class{
    NSLog(@"来了,老弟");
//注意这里会打印两次,因为方法交换,return 还调用了一次
    return [self lg_class]; // sel -> imp(class)
}
@end
[self class] 和 [super class] 区别
总结
上一篇 下一篇

猜你喜欢

热点阅读