關於內存管理的一些小問題

  1. 當我們用類似以下代碼測試retainCount的時候,發現輸出的並不是0.
    @autoreleasepool 
    {
    NSObject *obj = [[NSObject alloc] init];
    [obj release];
    NSLog(@"retainCount is %lu", obj.retainCount);
    }

    首先,以上代碼是錯誤的寫法。輸出之前,對象的內存已經被釋放,若內存被使用,這條語句就有可能使程序崩潰。
    對於輸出1的理解:系統知曉對象該被回收了,retainCount的值是否減1都沒有必要了,不減1,減少了一次內存寫操作,從而加速了內存的回收。
  2. 循環引用。
    當2個或2個以上對象,彼此引用,形成環,這種現象叫循環引用。如下圖:
    出現了循環引用,將會導致環上的對象都無法釋放空間。白白浪費內存。解決循環引用的問題主要有2種方式:
    *在適當的位置斷開一方的引用。它依賴於程序員有能力發現循環引用。
    *使用若引用。弱引用也持有對象,但不會增加引用計數。這樣就避免了環的產生。
  3. 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);
  4. 未完待續…
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章