- 當我們用類似以下代碼測試retainCount的時候,發現輸出的並不是0.
@autoreleasepool
{
NSObject *obj = [[NSObject alloc] init];
[obj release];
NSLog(@"retainCount is %lu", obj.retainCount);
}
首先,以上代碼是錯誤的寫法。輸出之前,對象的內存已經被釋放,若內存被使用,這條語句就有可能使程序崩潰。
對於輸出1的理解:系統知曉對象該被回收了,retainCount的值是否減1都沒有必要了,不減1,減少了一次內存寫操作,從而加速了內存的回收。 - 循環引用。
當2個或2個以上對象,彼此引用,形成環,這種現象叫循環引用。如下圖:
出現了循環引用,將會導致環上的對象都無法釋放空間。白白浪費內存。解決循環引用的問題主要有2種方式:
*在適當的位置斷開一方的引用。它依賴於程序員有能力發現循環引用。
*使用若引用。弱引用也持有對象,但不會增加引用計數。這樣就避免了環的產生。 - Core Foundation對象的內存管理
*Core Foundation是一個純C語言編寫的庫,Foundation庫是在其基礎上發展起來的。
*IOS中允許兩個框架對象之間的轉換。
CFStringRef aCFString = (CFStringRef)aNSString;
NSString aNSString = (NSString )aCFString;
ARC可以幫我們管理Foundation框架中的對象,但是當使用到Core Foundation框架中的對象時,ARC就無能爲力了。我們需要清除的是:對象轉換後,誰來釋放內存。
*MRC下,對象在轉換使用後,手動釋放掉就好。// NSString -> CFStringRef
NSString *nsStr1 = [NSString stringWithFormat:@"%d", 12345];
CFStringRef cfStr1 = (CFStringRef)nsStr1;
NSLog(@"%@", cfStr1);
CFRelease(cfStr1);
// CFStringRef -> NSString
CFStringRef cfStr2 = CFStringCreateWithCString(kCFAllocatorDefault, "12345", kCFStringEncodingUTF8);
NSString nsStr2 = (NSString )cfStr2;
NSLog(@"%@", nsStr2);
[nsStr2 release];
*ARC下,我們無法手動管理,但是要告訴轉換後,對象的所有權歸ARC還是我們自己。
__bridge 不改變對象的所有權,只是轉換而已。
__bridge_retained(CFBridgingRetain) 解除ARC的所有權。
__bridge_transfer(CFBridgingRelease) 給予ARC的所有權。// NSString -> CFStringRef,當然不改變所有權最好,還是由ARC管理
NSString *nsStr1 = [NSString stringWithFormat:@"%d", 12345];
CFStringRef cfStr1 = (__bridge CFStringRef)nsStr1;
NSLog(@"%@", cfStr1);
CFRelease(cfStr1);
// CFStringRef -> NSString,交給ARC多方便
CFStringRef cfStr2 = CFStringCreateWithCString(kCFAllocatorDefault, "12345", kCFStringEncodingUTF8);
NSString nsStr2 = (__bridge_transfer NSString )cfStr2;
NSLog(@"%@", nsStr2); - 未完待續…
關於內存管理的一些小問題
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.