iOS-Runtime之[self class]、[super
2020-07-11 本文已影响0人
枫叶无处漂泊
首先先看一段代码,看到下面代码输入是什么?
@implementation Son : Father
- (id)init {
self = [super init];
if (self) {
NSLog(@"%@", NSStringFromClass([self class]));
NSLog(@"%@", NSStringFromClass([super class]));
}
return self;
}
@end
运行结果:Son Son
看到运行结果,应该相当一部分的人认为是Son Father.
[self class]、[super class]内部实现
为啥是[super class]是Son,那我们就分析一下整个流程:
当[self class]、[super class]调用的是 -(Class)calss,但是[self class]、[super class]都没有实现 -(Class)class,通过消息传递一直会找到基类NSObject中,并且找到-(Class)class实现,可以在NSObject.m中找到这个方法:
- (Class)class {
return object_getClass(self);
}
object_getClass这个方法是获取当前对象的类对象。看看object_getClass内部实现
在runtime文件中可以找objc_class.m找到object_getClass的实现:
Class object_getClass(id obj) {
if (obj) return obj->getIsa();
else return Nil;
}
最终这个方法还是通过obj的isa指针,找到当前的对象的类对象。
我们可以clang -rewrite-objc命令将下面
NSLog(@"%@", NSStringFromClass([self class]));
NSLog(@"%@", NSStringFromClass([super class]));
转换成:
NSLog((NSString *)&__NSConstantStringImpl__var_folders_8k_cgm28r0d0bz94xnnrr606rf40000gn_T_Car_3f2069_mi_0, NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class"))));
NSLog((NSString *)&__NSConstantStringImpl__var_folders_8k_cgm28r0d0bz94xnnrr606rf40000gn_T_Son_3f2069_mi_1, NSStringFromClass(((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Son"))}, sel_registerName("class"))));
clang之后代码看出,调用[super class]的时候本质是调用:
objc_msgSendSuper(struct objc_super *super, SEL op, ...)
查看一下objc_super的定义如下:
struct objc_super {
/// Specifies an instance of a class.
__unsafe_unretained _Nonnull id receiver;
/// Specifies the particular superclass of the instance to message.
#if !defined(__cplusplus) && !__OBJC2__
/* For compatibility with old objc-runtime.h header */
__unsafe_unretained _Nonnull Class class;
#else
__unsafe_unretained _Nonnull Class super_class;
#endif
/* super_class is the first class to search */
};
objc_super内部结构可以看出,只要编译器看到出现super这个标志,就会让当前对象不管本类有没有实现都是去父类去找该方法,super就仅仅是一个编译指示器。
但是消息的接受还是self,最终在 NSObject 获取 isa 指针的时候获取的还是self的isa,执行的类对象还是Son。
结尾
- [super class]中的super只是一个编译指示器,就是让当前对象获取该方法,越过本类,直接从父类找。
- 消息的接受这还是本类self。