問題拋出
[self class]和 [super class]結(jié)果是否一樣呢
- (instancetype)init{
self = [super init];
if (self) {
NSLog(@"%@",NSStringFromClass([self class]));
NSLog(@"%@",NSStringFromClass([super class]));
//打印結(jié)果都為`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為當(dāng)前類.
[super class]
方法1 匯編
前邊[self class],調(diào)用 class方法的為 self對象,那么super是個什么呢?
我們不妨 Debug Workflow -> always show disassembly看匯編.
方法的調(diào)用說白了就是消息的發(fā)送過程.那么匯編有沒有類似objc_mesSend呢,發(fā)現(xiàn)[super class]其實是調(diào)用了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);
第一個參數(shù)為一個objc_super的結(jié)構(gòu)體
struct objc_super {
__unsafe_unretained _Nonnull id receiver;
__unsafe_unretained _Nonnull Class super_class;
};
那么[super class]就等價于
struct objc_super lg_super = {
//我們這里研究對象為當(dāng)前對象所以消息接收這位self
self,
class_getSuperclass([self class]),
};
objc_msgSendSuper(&lg_super,@selector(class))
打印結(jié)果依然為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 還調(diào)用了一次
return [self lg_class]; // sel -> imp(class)
}
@end
[self class] 和 [super class] 區(qū)別
- [super class] 速度更快
[self class]是正常的消息發(fā)送流程objc_msgSend,
方法的查找流程,先找自己->父類->......的一個遞歸流程
那么objc_msgSendSuper,跳過自己的查找流程,直接去父類里找,速度更快
還有一種比[super class]速度更快的[NSObject class]直接找根類
總結(jié)
[self class] 就是發(fā)送消息objc_msgSend,消息接受者是 self 方法編號:class
[super class] 本質(zhì)就是objc_msgSendSuper, 消息的接受者還是 self 方法編號:class 只是objc_msgSendSuper 會更快 直接跳過 self 的查找