iOS 無(wú)論是在MRC 還是ARC情況下 OC 都是用引用計(jì)數(shù)來管理內(nèi)存!
內(nèi)存管理的原則是: 誰(shuí)創(chuàng)建 誰(shuí)來釋放 ??誰(shuí)引用,誰(shuí)管理
例如MRC下:
NSObject * a = [NSObject alloc] init]; ? ?a 引用計(jì)數(shù)為 1
NSObject * b; //相同類型局部變量b
b = ?[a retain] ? //b這個(gè)時(shí)候可以使用a ? ? a的引用計(jì)數(shù)+1 ?= ?2
[a realse]; a的引用計(jì)數(shù)為1
[a realse];?a的引用計(jì)數(shù)為0
alloc 、new、 ?copy、 mutableCopy? 引用計(jì)數(shù) = 1 ? ? 生成并持有對(duì)象?
retain ?引用計(jì)數(shù)+1 ?并持有這個(gè)對(duì)象
strong ?引用計(jì)數(shù)+1 ? MRC下會(huì)做一次retain ARC下省略?
addobject 類似的 ?想要持有這個(gè)對(duì)象 ?引用計(jì)數(shù)+1 ?
release 引用計(jì)數(shù) - 1?
dealloc 引用計(jì)數(shù)為0的時(shí)候調(diào)用
ARC管理方法:
在ARC內(nèi)存管理機(jī)制中,id和其他對(duì)象類型變量必須是以下四個(gè)ownership qualifiers其中一個(gè)來修飾:
__strong ? 強(qiáng)引用
__weak ?弱引用?
__unsafe_unretained ??它是不安全的。它跟__weak相似,被它修飾的變量都不持有對(duì)象的所有權(quán),但當(dāng)變量指向的對(duì)象的RC為0時(shí),變量并不設(shè)置為nil,而是繼續(xù)保存對(duì)象的地址;這樣的話,對(duì)象有可能已經(jīng)釋放,但繼續(xù)訪問,就會(huì)造成非法訪問(Invalid Access)
__autoreleasing
NSAutoreleasePool?*pool?=?[[NSAutoreleasePool?alloc]?init];
//?put?object?into?pool
id?obj?=?[[NSObject?alloc]?init];
[obj?autorelease];
[pool?drain];
/*?超過autorelease?pool作用域范圍時(shí),obj會(huì)自動(dòng)調(diào)用release方法?*/
引入ARC之后,寫法比之前更加簡(jiǎn)潔:
@autoreleasepool?{
????id?__autoreleasing?obj?=?[[NSObject?alloc]?init];
}

ARC需要注意的事項(xiàng)?
1.過度使用?block?之后,無(wú)法解決循環(huán)引用問題
由于Core Foundation 框架并不支持 ARC,此時(shí)編譯器不知道該如何處理這個(gè)同時(shí)有 ObjC 指針和 CFTypeRef 指向的對(duì)象,所以除了轉(zhuǎn)換類型,還需指定內(nèi)存管理所有權(quán)的改變,可通過 __bridge、__bridge_retained 和 CFBridgingRetain、__bridge_transfer 和 CFBridgingRelease。
2.遇到底層?Core Foundation?對(duì)象,需要自己手工管理它們的引用計(jì)數(shù)時(shí),我們需轉(zhuǎn)換關(guān)鍵字,作為橋接轉(zhuǎn)換以解決 Core Foundation 對(duì)象與 Objective-C 對(duì)象相對(duì)轉(zhuǎn)換的問題:
__bridge:使用__bridge標(biāo)記可以在不修改相關(guān)對(duì)象的引用計(jì)數(shù)的情況下,將對(duì)象從Core Foundation框架數(shù)據(jù)類型轉(zhuǎn)換為Foundation框架數(shù)據(jù)類型(反之亦然)。
CF和OC對(duì)象轉(zhuǎn)化時(shí)只涉及對(duì)象類型不涉及對(duì)象所有權(quán)的轉(zhuǎn)化
只是聲明類型轉(zhuǎn)變,但是不做內(nèi)存管理規(guī)則的轉(zhuǎn)變
CFStringRef?s1?=?(__bridge?CFStringRef)?[[NSString?alloc]?initWithFormat:@"Hello,?%@!",?name];
只是做了 NSString 到 CFStringRef 的轉(zhuǎn)化,但管理規(guī)則未變,依然要用 Objective-C 類型的 ARC 來管理 s1,你不能用 CFRelease() 去釋放 s1。
__bridge_retained:會(huì)將相關(guān)對(duì)象的引用計(jì)數(shù)加 1,并且可以將Core Foundation框架數(shù)據(jù)類型對(duì)象轉(zhuǎn)換為Foundation框架數(shù)據(jù)類型對(duì)象,并從ARC接管對(duì)象的所有權(quán)。
NSString?*s1?=?[[NSString?alloc]?initWithFormat:@"Hello,?%@!",?name];
CFStringRef?s2?=?(__bridge_retained?CFStringRef)s1;
//?or?CFStringRef?s2?=?(CFStringRef)CFBridgingRetain(s1);
//?do?something?with?s2
//...
CFRelease(s2);?//?注意要在使用結(jié)束后加這個(gè)
__bridge_transfer:可以將Foundation框架數(shù)據(jù)類型對(duì)象轉(zhuǎn)換為Core Foundation框架數(shù)據(jù)類型對(duì)象,并且會(huì)將對(duì)象的所有權(quán)交給ARC管理,也就是說引用計(jì)數(shù)交由ARC管理;
__bridge_transfer or CFBridgingRelease
CFStringRef?result?=?CFURLCreateStringByAddingPercentEscapes(.?.?.);
NSString?*s?=?(__bridge_transfer?NSString?*)result;
//or?NSString?*s?=?(NSString?*)CFBridgingRelease(result);