[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;
}
最终渠道的obj
的isa
.
首先来看[self class]
因为这里obj
为student
对象,所以这里打印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] 区别
- [super class] 速度更快
[self class]
是正常的消息发送流程objc_msgSend
,
方法的查找流程,先找自己->父类->......
的一个递归流程
那么objc_msgSendSuper
,跳过自己的查找流程,直接去父类里找,速度更快
还有一种比[super class]
速度更快的[NSObject class]
直接找根类
总结
-
[self class] 就是发送消息objc_msgSend,消息接受者是 self 方法编号:class
-
[super class] 本质就是objc_msgSendSuper, 消息的接受者还是 self 方法编号:class 只是objc_msgSendSuper 会更快 直接跳过 self 的查找