2010-04-30 44 views
2

我只是自己熟悉與CLLocationManager,發現包含以下init()方法的若干樣本的類定義:爲什麼在init方法中爲iVar定義調用autorelease?

- (id) init { 
    self = [super init]; 

    if (self != nil) { 
     self.locationManager = [[[CLLocationManager alloc] init] autorelease]; 
     self.locationManager.delegate = self; 
    } 
    return self; 
} 

- (void)dealloc { 
    [self.locationManager release]; 
    [super dealloc]; 
} 

我不明白爲什麼伊娃將被自動釋放。這不是否意味着它在init方法結束時被釋放了嗎?

我也很疑惑,看到相同的示例代碼在dealloc方法中有iVar版本。

有什麼想法? '

回答

7

locationManager是可能與retain屬性一起設置的屬性。

基本上,如果你只寫:

self.locationManager = [[CLLocationManager alloc] init]; 

左側self.locationManager二傳手保留所分配的CLLocationManager的參考。但右側CLLocationManager參考本身從未發佈。該管理器的保留計數從未達到零,並且對象永遠不會消失 - 這會導致內存泄漏。

有兩種方法可以解決這個問題。無論autorelease當你在代碼中見過分配的對象段,您引用的 - 或者你的分配對象分配給一個臨時變量,保留臨時變量的locationManager屬性,然後明確地釋放臨時變量:

CLLocationManager *_temporaryReference = [[CLLocationManager alloc] init]; 
self.locationManager = _temporaryReference; // this is retained 
[_temporaryReference release]; 

這兩種方法在內存管理方面都是等價的。有些人更喜歡這種第二種方法,因爲他們不喜歡等待autorelease池被「清空」,特別是在像iPhone這樣的低內存設備上,這可以更好地控制對象的使用壽命。

Apple的Objective-C Programming Language文檔更詳細地解釋了此屬性。

+0

嗨亞歷克斯,但你再次解除我的困惑。非常感謝 – iFloh 2010-04-30 12:35:38

1

如果您的self.locationManager是保留它的屬性,那麼它會設置保留。通過執行alloc,您可以將保留計數設置爲+1,這意味着在函數結束時它是+2。當你說autorelease時,它會是+1(因爲保留屬性)。您也可以在將它設置爲屬性後將其明確釋放,但是您所做的是更少的代碼並且易於閱讀。

+2

這是誤導。自動釋放不會更改保留計數。它所做的就是將對象添加到自動釋放池中,當池被耗盡時它將向對象發送釋放。無論如何,最好不要考慮保留數量。只考慮所有權。該對象是使用alloc方法獲得的,因此您擁有該對象。因此,您必須釋放它或自動釋放它,以便在您完成所有權後放棄所有權。您可以安全地留下財產,以清理自己的所有權問題。 – JeremyP 2010-04-30 11:17:47

+0

感謝您的澄清。我認爲這很清楚,並且很高興傑里米的留存教訓,因爲這是一切歸結爲... – iFloh 2010-04-30 12:35:03

+0

傑里米的評論是重要的。 「自動釋放池」可能應該被稱爲「自動釋放列表」,因爲人們經常看到「池」這個詞並錯誤地認爲它像堆或實際包含對象的內存區。 Autorelease只是一個延遲的消息傳遞工具。 – NSResponder 2010-05-01 15:30:44

1

有沒有臨時變量或自動釋放一種替代方案:

locationManager = [[CLLocationManager alloc] init]; 

如果不使用self.locationManager你是不是調用類的該變量的setter方法和結果不增加保留計數2.編譯器將這些分配更改爲[self setLocationManager: locationManager];。這假設你已經將該變量原型化爲保留。

如果它是一個類變量(它是),你可以只做任務。這是否是好的編碼練習是值得商榷的,但在我看來,這取決於課堂開始的位置。

相關問題