iOS arc VS mrc學習筆記

躍然發表於2015-03-02

一、* Core Foundation與objective-c Object進行交換 *

對於Core Foundation與objective-cObject進行交換時,需要用到的ARC管理機制有:

(1) (__bridge_transfer) op or alternatively CFBridgingRelease(op) is used to consume a retain-count of a CFTypeRef while transferring it over to ARC. This could also be represented by

        id someObj =(__bridge <NSType>) op; 
       CFRelease(op);

(2) (__bridge_retained) op or alternatively CFBridgingRetain(op) is used to hand an NSObject over to CF-land while giving it a +1 retain count. You should handle a CFTypeRef you create this way the same as you would handle a result of CFStringCreateCopy().This could also be represented by

CFRetain((__bridge CFType)op); 
CFTypeRef someTypeRef =(__bridge CFType)op;

(3) __bridge just casts between pointer-land and Objective-C object-land. If you have no inclination to use the conversions above, use this one.

二、* ARC和IOS4 *

ARC在IOS4是沒有 __weak 關鍵字的,需要使用 unsafe_unretained來代替。

三、* ARC中的記憶體洩露 *

使用了ARC也並不意味著我們的工程裡面不會出現記憶體洩露了。在ARC機制下,最常見導致記憶體洩露的是迴圈強引用。容易出現的場合有:

①Outlet型別指標

Outlet型別的指標變數應該用weak屬性來宣告

②委託

一定要將delegate的屬性設為weak,原因我就不解釋了,實在不明白,請猛擊這裡

③block

下面這段程式碼,在MRC條件下是沒有問題的:

MyViewController * __block myController = [[MyViewController alloc] init…];  
// ...  
myController.completionHandler =  ^(NSInteger result) {  
    [myController dismissViewControllerAnimated:YES completion:nil];  
}; 

但是在ARC條件下,就會記憶體洩露,導致myController指向的物件無法釋放。
原因是,__block id x宣告的變數x用於block中時,MRC條件下是不會增加x的引用計數,但是在ARC條件下,會使x得引用計數加一,請各位務必注意!!!!!!!!!!!!

上述問題程式碼有以下幾種解決方案:

方案一:

MyViewController * __block myController = [[MyViewController alloc] init…];  
// ...  
myController.completionHandler =  ^(NSInteger result) {  
    [myController dismissViewControllerAnimated:YES completion:nil];  
    myController = nil;  
}; 

最簡單的解決辦法,在block中使用完myController時,是它指向nil,沒有strong型別的指標指向myController指向的物件時,該物件就回被釋放掉。

方案二:

MyViewController *myController = [[MyViewController alloc] init…];  
// ...  
MyViewController * __weak weakMyViewController = myController;  
myController.completionHandler =  ^(NSInteger result) {  
    [weakMyViewController dismissViewControllerAnimated:YES completion:nil];  
};  

該方案使用了一個臨時的__weak型別的指標weakMyViewController,在block中使用該指標不會導致引用計數加一,但卻存在隱患,當該物件在外部被釋放時,block裡面執行的操作就無效了。下面的方案三可以解決這個問題。

方案三:

MyViewController *myController = [[MyViewController alloc] init…];  
// ...  
MyViewController * __weak weakMyController = myController;  
myController.completionHandler =  ^(NSInteger result) {  
    MyViewController *strongMyController = weakMyController;  
    if (strongMyController) {  
        // ...  
        [strongMyController dismissViewControllerAnimated:YES completion:nil];  
        // ...  
    }  
    else {  
        // Probably nothing...  
    }  
};  

即在block中使用myController物件之前再宣告一個臨時的strong型別的指標,指向weak型別的指標,這時strongMyController指標就變成了有效的強引用,其指向的物件就能保證不被釋放掉。

④定時器

定時器也是非常容易產生記憶體洩露的地方。比如下面的程式碼

@implementation AnimatedView  
{  
  NSTimer *timer;  
}  

- (id)initWithCoder:(NSCoder *)aDecoder  
{  
  
  if ((self = [super initWithCoder:aDecoder])){  
    timer = [NSTimer scheduledTimerWithT    imeInterval:0.1  
    target:self  
    selector:@selector(handleTimer:)  
    userInfo:nil  
    repeats:YES];  
  }  
  return self;  
}  
- (void)dealloc  
{   
  [timer invalidate];  
}  
- (void)handleTimer:(NSTimer*)timer  
{  
  //do something  
}  

乍一看這段程式碼沒啥問題,但是執行起來才發現dealloc方法是不會被呼叫的,self有一個timer的強引用,timer又有一個self的強引用,典型的迴圈引用!

解決方法是將timer的屬性設定為__weak。

四、* @autoreleasepool 和 NSAutoreleasePool *

ARC中是不支援使用NSAutoreleasePool的,但是可以使用@autoreleasepool代替。@autoreleasepool既可以用在ARC環境中,也可以用在非ARC環境中,而且效率要比前者高,蘋果官網中是這樣描述的:

ARC provides @autoreleasepool blocks instead. These have an advantage of being more efficient than NSAutoreleasePool. 

五、* 使用ARC需要遵守的新規則 *

①不要在dealloc方法中呼叫[super dealloc];

②不能使用 retain/release/retainCount/autorelease

③不能使用 NSAllocateObject/NSDeallocateObject

④不能使用 NSZone

⑤Objective-C 物件不能作為C語言結構體(struct/union)的成員

參考連結:

  1. arc & mrc這不是技術路線問題。

  2. Objective-c的記憶體管理MRC與ARC

  3. ARC使用心得(二)

  4. Performance Comparison: cocos2d-iphone v2 vs v3 vs Sparrow and ARC vs MRC

  5. iPhone開發之深入淺出 (4) — ARC之迴圈參照
  6. Transitioning to ARC Release Notes

相關文章