若是在网上搜关于内存管理最多的总结就是谁持有谁释放。可是内存管理往多的说是有好多东西的,我今天只写一下关于strong、weak和autoreleas(之后会写片博客,会介绍到它们的底层运做)。在此也给想更深刻了解的伙伴们推荐本书一个日本前辈写的Objective-C高级编程,我本身讲内存管理梳理的差很少清晰的时,多亏了它。编程
关于内存管理,我原来有一段时间都对strong、weak傻傻的区分不清楚,也没有多少兴趣去了解。直到一天我真的在使用代理中碰到了神奇的内存泄漏,害死我了,通过调查锁定了凶手就是weak,根本的罪魁祸首是我对修饰符使用的只知其一;不知其二。但愿这点理解能起到一点点帮助。oop
a、区分strong、weak布局
strong:strong为强引用,是id类型对象和对象默认的全部权修饰符(咱们平时在@property中指定了属性的修饰strong、weak、或者是assign,可是在建立其余对象的时候,系统帮咱们默认加了_strong修饰符进行内存管理),使用strong修饰的对象在超出其变量做用域时,即该变量被废弃时,会释放其被赋予的对象。使用strong会对对象被持有对象的引用计数产生影响,当其持用一其余对象的时候,会将其余对象的引用计数加1,当出做用域强引用失效时,会释放掉对其持有对象的持有。学习
weak:weak为若引用。weak修饰的对象,当其持有其余对象的时候不会对其余对象的引用计数形成影响,weak的存在很好的解决掉了循环引用。当它所持有的对象销毁时,weak修饰的对象会自动置nil。关于weak的实现我简单的多说一点,由于我本身原来对此很好奇而后多方了解了下,在此分享给你们,若是有错欢迎更但愿你们纠正。代理
runtime会对注册的类进行布局,对于weak对象会放入一个hash表中。使用weak对象的内存地址做为key,当weak对象指向的对象的引用计数为0的时候执行置nil。执行过程为以weak对象的内存地址为索引,在hash表中找到对应的weak修饰对象,将其置为nil。对象
b、做用的区分索引
讨论他两避免不了循环引用和自引用。说白了就是光使用strong容易出现内存泄漏即在对象出了做用域(也就是大括号)后不能获得释放。以下例子:内存
分别建立对象a、b,他们分别被对象A、B持有(当咱们没有指定修饰权时,咱们建立的对象默认的修饰权为_strong,也就是强引用)。而后对象B中有个成员变量objB又持有了a一次,对象A中的成员变量abjA有持有了b一次。这样,就会造成循环引用。由于在出了做用域后A、B的强引用失效,释放掉了对a、b的持有,可是他们中的成员变量并无释放掉对于a、b的持有。此时发生内存泄漏,也就是咱们所说的循环引用。作用域
上面刚刚说过,weak不会对引用计数形成影响,也就不会影响到有关对象的释放。因此咱们在关键部位使用weak修饰并不会形成对有关对象的引用计数形成影响,从而使得已经出了做用域可是有关该释放的对象并不能获得释放,形成内存泄漏。博客
c、autoreleas有关问题
之因此说autoreleas是由于原先在网上学习内存管理这块的时候被误导过,在此但愿你们注意。autoreleas释放池中对对象的释放我原来好奇过,上网查的时候最后造成的答案是做用域。可是随着对O-C更加深刻的学习,发现了它对于其内部寄存对象的释放是和runloop有关系的。
iOS程序由许多的runloop组成,每个runloop都会有一个Autorelease Pool并在末尾进行释放。
好比咱们点击一个button,一个button从等待到点击到响应就存在一次循环,期间就前程到对象的建立和最后Autorelease Pool在runloop即将结束时的销毁所有对象。