iOS学习引擎iOS Developer - RuntimeiOS 开发

学习runtime中的self和super

2016-08-30  本文已影响92人  iOSDevVicky

我们先来看已到习题:

下面代码输出的会是什么?这个类名叫test,继承自NSObjec

图1

我只能肯定的告诉大家,这里输出的都是test.

self是类的隐藏参数,指向当前调用方法的类的实例,而super是一个关键字,是一个系统标识符,这里的self调用class方法会先从本类找,如果找不到就去父类找,而[super class]是在调用方法前告诉编译器在调用这个方法之前先要调用父类的class方法.不管上面[self class] 还是[super class]接收消息的对象都是test.

那我们如何验证啦?

懵逼

好吧那我现在就给大家分析一下

我们可以使用clang命令来重写命令:

$ clang -rewrite-objc test.m

然后我们发现我们刚才的打印转换成了这样

NSLog((NSString *)&__NSConstantStringImpl__var_folders_gm_0jk35cwn1d3326x0061qym280000gn_T_main_a5cecc_mi_0, NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class"))));

NSLog((NSString *)&__NSConstantStringImpl__var_folders_gm_0jk35cwn1d3326x0061qym280000gn_T_main_a5cecc_mi_1, NSStringFromClass(((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){ (id)self, (id)class_getSuperclass(objc_getClass("test")) }, sel_registerName("class"))));

先看第一个我们都知道oc语言的消息机制所以我们看编译后的代码,都从objc_mgsSend看起.我们明显的看到[self class]调用时objc_msgSend()函数的第一个参数是self,而[super class]则调用的是objc_msgSendSuper()函数,第一个参数是一个结构体

objc_super

第一个消息接受者类似于上一个的self,第二个是记录当前类的父类是什么.

所以当调用[self class]时,转化为objc_msgSend时,第一个参数是test的实例对象,然后在test这个类里面查找class这个方法,然后就去父类查找.所以我们看到第一个输出的是test

第二个调用[super class],转化成objc_msgSendSuper()函数,第一个参数是一个结构体,第一个成员是self,第二个成员是(id)class_getSuperclass(objc_getClass("test")也就是NSObect,实际上该函数应该输出NSObject,但是通过第二步先去NSObjec中找class方法,找到了,然后调用这个方法时:objc_msgSend(objc_super->receiver, @selector(class))又被转换成和第一种调用相同.所以输出的是test.

好了今天的学习就到这了,要明确super和self的不同.

总结,super是关键字,会告诉编译器,在调用改方法前,先去调用父类的方法.

而self会直接转换成objc_msgSend消息机制,接受者是self.而super会转化成objc_msgSuperSend(),单最终的耗时会转换成与[self class]相同的调用.

谢谢

本人联系方式:qq:513961360

email:513961360@qq.com

也可以加我们的qq群希望能与朋友们一起聊天和学习.群里还有很多iOS开发者,帮助我们解决问题,并且同时学习.

qq群号:580284575

上一篇下一篇

猜你喜欢

热点阅读