2011-05-19 22 views
6

我在一些示例代碼中看到autorelease被使用。在需要時我不熟悉這些實例。例如,如果我創建一個註釋對象使用點語法設置retain屬性時使用autorelease?

頭文件

@interface someViewController: UIViewController 
{ 
    Annotation *annotation; 
} 

@property (nonatomic, retain) Annotation *annotation; 

@end 

實現文件

@implementation someViewController 
@synthesize annotation 
@end 

問:這是不是正確的做法,如果我在這樣的實現文件初始化我的註釋對象?

self.annotation = [[Annotation alloc] initWithCoordinate:location]; 

我需要爲此設置autorelease嗎?或者我可以按照正常的方式進行操作,並在dealloc方法中添加發布版本?

+1

[自動釋放與釋放(http://stackoverflow.com/questions/4077159/autorelease-vs-release)和可能的複製還有,如果你花時間去閱讀,這將回答這個問題很多很多其他問題他們:[搜索:iPhone保留屬性autorelease](http://stackoverflow.com/search?q=iphone+retain+property+autorelease)這:[發佈/ autorelease混淆](http://stackoverflow.com/questions/ 1121343/release-autorelease-confusion-in-cocoa-for-iphone)可能是最好的之一。 – 2011-05-19 07:45:26

回答

15

這是正確的:

self.annotation = [[[Annotation alloc] initWithCoordinate:location] autorelease];

因爲註解屬性被聲明爲保留財產,因此分配給它會增加其保留計數。

您還需要,都一樣地發佈-dealloc中的self.annotation。

在短

  1. init將設置保留計數爲1;

  2. 賦值給self.annotation,將它設置爲2;

  3. 當主循環再次執行時,autorelease會將其設置回1;

  4. release in dealloc將保留計數設置爲0,以便該對象將被釋放);

autorelease最好的辦法是下面的,在我看來:autorelease將「時間表」,用於在未來的一段(附近)點(你的對象是「自動」 release通常在控制流程前進回到主循環,但細節隱藏在蘋果手中)。

autoreleaseinit結合最有用,特別是在以下情況:

  1. 當你init一個局部變量,這樣你就不必release它超出範圍它明確之前(主循環會爲你做);

  2. 當你返回一個指向你剛剛創建的對象的指針而不保留它的所有權時(create/make*類型的選擇器的典型情況,接收器需要它獲得所有權的retain);

  3. 與性質retain,當你爲他們分配的對象,他們應該擁有獨特的;

  4. 與遞增保留計數(NSMutableArrayNSMutableDictionary,等)的數據結構:通常應autorelease新時將其添加到這樣的數據結構init編輯對象。

從案例2

分開,顯而易見的是,使用autorelease是爲了提高代碼的可讀性,並減少潛在的錯誤(這意味着在所有的其他情況下,你可以簡單地release明確你的分配後的對象或範圍的末尾)。

使用屬性時,您必須始終檢查它們是否是retainassign/的情況;在第一種情況下,將新編輯的物件分配給物業通常需要autorelease

無論如何,我會建議至少走過場很多教程的一個上memory management for iOS

+0

如果你寫了'annotation = [[Annotation alloc] initWithCoordinate:location];''沒有'self',一個快速的錯誤就不會增加保留計數。 – dombesz 2011-06-27 14:43:48

2

自動釋放講的是對象離開範圍之前釋放自己。

有時,當你的代碼,你會遇到這樣的事情

- (void)doSomething 
{ 
    if(true) 
    { 
     NSString *foo = [[NSString alloc] initWithString:@"foo"]; 

     //Some execution here 

     [foo release]; 
    } 
} 

- (void)doSomething 
{ 
    if(true) 
    { 
     //By doing this is telling to to release foo object before getting out of the scope 
     //which is similar with above practice 
     NSString *foo = [[[NSString alloc] initWithString:@"foo"] autorelease]; 

     //Or you can do it this way 
     NSString *foo = [[NSString alloc] initWithString:@"foo"]; 
     [foo autorelease]; 

     //Some execution carry on, it'll release foo before entering next scope 

    } 

//這是出於範圍 }的

當然,釋放對象並不意味着重新分配對象。 有時您保留該對象,以便您仍可以在其範圍之外使用它。

從你的問題來看,如果你的對象位於你的頭文件/接口內。 你應該在dealloc方法中釋放它。 CMIIW。

+0

只是澄清,我的理解是,即使對象是在頭文件中,我們可能仍然需要執行autorelease,例如self.annotation = [[Annotation alloc] init ...發生。那是對的嗎? – Zhen 2011-05-19 07:55:04

+0

@ Zhen通常你會初始化你的接口對象(甚至使它爲零)。因此釋放dealloc是必須的。但是如果有機會再次初始化對象(由於丟失了以前的內存地址,這會導致內存泄漏),是的,您可以設置autorelease。請記住,當我們分配和初始化時,我們正在討論內存地址。這就是我所知道的,如果你想了解更多信息,你可以閱讀/詢問有經驗的程序員。 – sayzlim 2011-05-19 08:05:03