工具介绍
开发实践
内存管理
现在都是arc,想看非arc情况,给对应编译文件添加编译参数 -fno-objc-arc
开启手动管理引用计数模式
为什么需要引用计数
在通常的函数内,通常是使用一个临时的对象,是不需要修改它的引用计数的
,只需要在函数返回前将对象销毁就可以了.
引用计数真正派上用场,是在面向对象的程序设计架构中,用于对象之间传递和共享数据.
1 | NSObject *obj = [NSObject alloc]init]; |
循环引用的问题 reference cycles
引用计数这种内存管理方式虽然简单,但是有一个比较大的瑕疵,不能很好地解决循环引用的问题
例:对象a和b相互引用了对方作为自己的成员变量,只有当自己销毁时,才能将成员变脸的引用计数减1.而对象a的销毁依赖于对象b的销毁,对象b的销毁又依赖于a的销毁,就造成了循环引用的问题,即使外界没有任何指针能够访问他们了,他们也无法被释放.
不止两个对象,多个对象更容易形成环状.
解决循环引用的问题,一种是手动发现这个循环引用,主动把这个环断开,这又回到了”谁申请谁释放”的内存管理时代,这种方法要求比较高,需要知道在什么时候断开循环引用回收内存,这种方法并不常用,更常见的是使用弱引用的方法.
若引用虽然持有对象,但是并不增加引用计数,这样就避免了循环引用的产生
弱引用通常用在delegate中.
使用xcode检测循环引用.
循环引用的代码
1 | NSMutableArray *first = [NSMutableArray array]; |
product-profile-leaks-cycles/root
ARC
有两种疑惑:
- 从MRC过来的老一代iOS开发程序员,对ARC持怀疑态度,不敢用
- 11年之后,从ARC开始学习的新手,完全不知道引用计数是啥,对ARC有很强的依赖,但不知道ARC内部的原理
Core Foundation对象的内存管理
底层的Core Foundation对象,大多以XxxCreateWithXxx的方式创建
1 | 创建一个string对象 |
CFRetain ,CFRelease 方法,对应Objective-C的retain, release方法
所以对于底层的Core Foundation对象,只需要延续以前的手工管理引用计数的方法就可以了
Core Foundation与Objective-C对象相互转换的问题,告诉编译器,转换的过程中,引用计数如何调整.
- _bridge只做类型转换,不修改相关对象的引用计数
- _bridge_retained,类型转换后,引用计数加1
- _bridge_transfer,类型转换后,将该对象的引用计数交给ARC管理
iOS开发底层原理
Objective-C对象模型
isa指针
可以通过cmd+shift+o快捷键查看NSObject, objc.h和runtime的头文件查看相应的代码结构
NSObject就是一个包含isa指针的结构体
每一个类实际上也是一个对象,也有一个名为isa的指针
因为类是一个对象,所以它必须是另一个类的实例,这个类就是元类(metaclass)
元类保存了类方法的列表,当一个类方法被调用时,元类会首先查找它自己本身是否有该类方法的实现,如果没有,该元类会向它的父类查找,一直找到继承链的头
元类也是一个对象,那么元类的isa指针又指向哪呢?为了设计上的完整,所有元类的isa指针都会指向一个根元类(root metaclass).根元类的isa指针指向自己,这样就形成了一个闭环