这个也许是问得最多的问题了吧。全部这些问题每每来源于3个地方,一、不了解底层机制;二、没有吃透规则; 三、不了解经常使用container的Reference Counting特性,或着说没有下功夫去看对应文档。 html
1. 底层机制 ios
你们是否知道从旧时代的MRC到ARC机制到底意味着什么呢? 为何ARC从开发速度,到执行速度和稳定性都要优于MRC?开发速度不言而喻,你少写不少release代码,甚至不多去操心这部分。执行速度呢?这个还要从runtime提及,还记得我在第2点说得一句话么:“Runtime is everything between your each function call.” 程序员
MRC是一个古老的内存管理哲学,谁分配谁释放。经过counting来计数到底该资源有几个使用者。道理很简单,可是每每简单的东西人却会犯错。历来没有一个程序员能够充满信心的说,我写得代码历来没有过内存泄露。这样来看,咱们就更须要让程序能够本身处理这个管理机制,这就须要把这个机制放到runtime里。 算法
因此MRC->ARC就是把内存管理部分从普通开发者的函数中移到了函数外的runtime中。由于runtime的开发原型简单,逻辑层次更高,因此作这个开发和管理出错的几率更小。实际上编译器开发人员对这部分通过无数次测试,因此能够说用ARC几乎不会出错。另外因为编译的额外优化,使得这个部分比程序员本身写得代码要快速不少。并且对于一些通用的开发模式,例如autorelease对象,ARC有更优秀的算法保证autoreleasepool里的对象更少。 app
2. RC规则 函数
首先说一下RC是什么,r-Reference参照,引用 c-counting计数, RC就是引用计数。俗话说就是记录使用者的数量。 例如如今我有一个房间空着,你们能够进去随意使用,可是你进门前,须要给门口的计数牌子+1,
出门时候-1。 这时候这个门口的牌子就是该房间里的人数。一但这个牌子变为0我就能够把房间关闭。 测试
这个规则可让NSObject决定是否是要释放内存。当一个对象alloc时候,系统分配其一块内存而且object自动计数retainCount=1 这时候每当[object retain]一次retainCount+1(这里虽然简写也是rc不过是巧合或者当时开发人员故意选的retain这个词吧)每次[object release]时候retainCount-1 当retainCount==0时候object就真正把这快内存还给系统。 优化
3. 经常使用container的Reference Counting特性 ui
这个规则很简单把。可是这块确实让新手最头疼的地方。问题出在,新手总想去验证RC规则,又老是发现和本身的指望不符合。无数次看到有人写下以下句子 this
NSLog(@"%d",[object retainCount]); while([object retainCount]>0){ [object release]; }
固然了,我也作过相似的动做,那种但愿一切尽在掌握中的心态。可是你会看到其余人告诉这么作彻底没有意义。rc does not work this way. 也许这样的暴力释放会起做用,可是retainCount并非用来作这个的。每一个数字意味着有其它对象引用该资源,这样的暴力释放很容易致使程序崩溃。这个数字也许并非你心目中的哪一个。由于你很难跟踪到底哪些对象引用的该资源。你用代码创建的资源不光只有你的代码才会用到,你调用的各类Framework,Framework调用的Framework,都有可能改变这个资源的retainCount.
因此去验证RC规则不是明智之举。你能作的就是理解规则,使用规则,读文档了解container的引用特性。或者干脆移到ARC上面,让runtime环境处理这些问题。最后说一下不用arc的状况。目前状况来看,有很多第三方的库并未支持ARC,因此若是你的旧项目使用了这些库,请检查是否做者发布了新版本,或者你须要本身修正支持ARC。
最后补充记录下ARC的新规则(ARC Enforces New Rules):
为了正常运转,ARC使用了一些在使用其它编译模式下没有的新规则。这些规则意在提供彻底可靠的内存管理模型;在某些状况下,它们仅使用最佳实践方法,在其它状况下,它们仅简化你的代码或明显的作出推论告知你不须要处理内存管理。若是你违反了这些规则,你会立刻获得一个编译期错误,而不是在运行期可能会显现的一个狡猾的bug。 // Won't work: @property NSString *newTitle; // Works: @property (getter=theNewTitle) NSString *newTitle; |