3.消息传递和消息转发
消息传递
(1)核心方法
1 | void objc_msgSend(void /*id self, SEL op, ...*/) |
objc_super
结构体解析:
1 | void objc_msgSendSuper(void /* struct objc_super *super, SEL op, ...*/) |
(2)编译器转化如下:
1 | [self method] <==> objc_msgSend(self, @selector(method)) |
(3)调用方法时消息传递机制流程
缓存查找: Hash查找
方法列表查找: 已排序(二分法查找), 未排序(一般遍历)
父类逐级查找: 取当前类的superclass查找, 直到superclass =nil停止
(4)案例
1.来源: iOS 程序员 6 级考试
1 | @implementation Son : Father |
答案:都输出”Son”
解释:objc中super是编译器标示符,并不像self一样是一个对象,遇到向super发的方法时会转译成objc_msgSendSuper(...),而参数中的对象还是self,于是从父类开始沿继承链寻找- class这个方法,最后在NSObject中找到(若无override),此时,[self class]和[super class]已经等价了。
2.[obj foo]
和 objc_Sendmsg()
函数有什么关系?
答案: 实际上编译器转化后, [obj foo]就成了下面的样子
objc_Sendmsg(obj, @selector(foo))
3.runtime如何通过selector找到对应的IMP地址的?
答案: 问题的实质就是消息的传递流程: 简述 由缓存->类的方法列表->逐级父类方法列表 消息的传递机制
4.能否像编译后的类增加实例变量?
答案:不能 , 如果是动态添加的类, 就可以增加实例变量
消息转发
(1)核心方法
1 | // 方法解析 |
(2)转发流程
流程图
代码段
1 | + (BOOL)resolveInstanceMethod:(SEL)sel { |
Method Swizzling
(1)核心方法
1 | // 获取实例方法 |
(2)使用
1 | + (void)load { |
注意: + (void)load
方法在文件加载时,且在mian()
之前调用, 所以程序启动后, method1和method2方法其实已经交换了
4.内存管理
弱引用管理
探讨问题:
当一个obj废弃时,指向它的weak指针为何会自动置为nil?
解析: 当一个对象被dealloc()之后, 在dealloc的内部实现中会调用弱引用清除函数 weak_clear_no_lock(), 然后在这个函数的内部实现中, 会根据当前对象指针查找弱引用表, 拿到当前对象所相对应的弱引用列表, 遍历这个列表的所有弱引用指针都置为nil.
自动释放池
- 本文作者: 醉疏狂
- 本文链接: https://hubin97.github.io/2020/02/10/知识点总结2/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!