MRC現(xiàn)在很少用了, 但原理依舊在那里, ARC環(huán)境下, 不需要手動(dòng)retain, release了, 但其實(shí)只是編譯器幫你做了這些事情.
那么iOS引用計(jì)數(shù)究竟是怎么回事了, 我們先從assign關(guān)鍵字說起
現(xiàn)在提到assign關(guān)鍵字, 一般用來修飾非OC對象, 比如一些基本數(shù)據(jù)類型, 比如NSInteger, BOOL, 以及C語言的基本數(shù)據(jù)類型, int, double之類的, 因?yàn)?code>assign關(guān)鍵字只是分配一塊內(nèi)存空間, 并沒有做任何關(guān)于引用計(jì)數(shù)的操作.
所以, 在ARC環(huán)境下, 有點(diǎn)類似于weak關(guān)鍵字, 但跟weak關(guān)鍵字修飾的屬性的區(qū)別是, weak關(guān)鍵字修飾的對象, 會(huì)加入弱引用表中, 對象被銷毀時(shí), 指向?qū)ο蟮闹羔樢矔?huì)被置為 nil, 但是assign關(guān)鍵字修飾的對象, 對象被銷毀時(shí), 指向?qū)ο蟮膬?nèi)存并不會(huì)置為nil, 這時(shí)候在去訪問那片內(nèi)存空間, 是非常危險(xiǎn)的, 會(huì)產(chǎn)生EXEC_BAD_ACCESS

比如在上面圖示的例子中, 先跳轉(zhuǎn)到一個(gè)新的控制器, 然后返回控制器的時(shí)候, 控制器會(huì)被銷毀, 這時(shí)候, 再去訪問用assign關(guān)鍵字修飾的控制器對象, 就會(huì)報(bào)EXEC_BAD_ACCESS.
所以, 在ARC環(huán)境下, 是不能用assign去修飾OC對象的.
那么在MRC環(huán)境下呢? 在MRC環(huán)境下, 默認(rèn)就是assign, 但是, 用assign修飾也是會(huì)有問題的.

比如在上面的代碼中, p1.aCat 指向的那片內(nèi)存空間已經(jīng)被提前release了, 后面仍然去訪問, 那就會(huì)出現(xiàn)EXEC_BAD_ACCESS.
但如果此時(shí)用retain修飾就不會(huì)有問題:

這是因?yàn)? p1.aCat = cat實(shí)際上給p1發(fā)送setACat消息:
- (void)setACat:(Cat *)aCat {
if (_aCat != aCat) {
[_aCat release];
_aCat = aCat;
[aCat retain];
}
}
本質(zhì)上就是這樣的, 先判斷舊的對象和新賦值的對象是不是同一個(gè)對象, 如果是, 就什么都不做, 如果不一樣, 就先給舊對象發(fā)送release消息, 然后賦值操作, 最后, 將新對象的引用計(jì)數(shù)+1, 這就是retain關(guān)鍵字做的事情, 所以如果重復(fù)賦值, 引用計(jì)數(shù)也不會(huì)變化
在MRC環(huán)境下, 使用retain關(guān)鍵字, 除了在set方法引用計(jì)數(shù)+1, 在get方法中, 并不會(huì)對對象引用計(jì)數(shù)+1

如上圖所示, 在
MRC環(huán)境下, 引用計(jì)數(shù)為2
但是在ARC環(huán)境下, 使用retain關(guān)鍵字, 除了在set方法引用計(jì)數(shù)+1, 在get方法中, 也會(huì)對對象引用計(jì)數(shù)+1

事實(shí)上在ARC環(huán)境下使用retain和strong的效果是一樣的:

也可以參考這張圖:
在ARC環(huán)境下使用以下關(guān)鍵字的效果:
