2012-06-14 37 views
0

我在添加到視圖後檢查子視圖的retainCount。代碼:爲內存泄漏添加子視圖和釋放(retainCount)

- (void) loadView{ 
    //... 
    toolbar = [[UIToolbar alloc] initWithFrame:nil]; 
    [[self view] addSubView:toolbar]; 
} 

- (void) dealloc{ 
    NSLog(@"count=%d", [toolbar retainCount]); // count=2 
    [toolbar removeFromSuperView]; 
    NSLog(@"count=%d", [toolbar retainCount]); // count=1 
    [toolbar release] 
    NSLog(@"count=%d", [toolbar retainCount]); // count=1 
    toolbar = nil; 
    NSLog(@"count=%d", [toolbar retainCount]); // count=0 
} 

從這個代碼中的dealloc {},我有一些問題:

1,工具欄的第一個日誌retainCount是2,因爲在init之後,工具欄,並添加到自視圖,該retaincount將變得2.

2,工具欄removeFromSuperView後,retainCount將變得1.

3,調用釋放方法的工具欄後,retainCount仍爲1,它不能成爲0.在我的選擇,因爲超級視圖仍然是工具欄(自我查看不是釋放),所以工具欄不能減少到0.

4,如果調用工具欄設置爲零,retainCount將爲0.此日誌是無用的。

我的問題是:

一)工具欄調用removeFromSuperView和發佈API,結果是一樣的,工具欄retainCount只會變得比1,所以如果我測試的代碼只使用他們每個人,結果是一樣的。那麼,我可以總結用戶只能調用每個API嗎?

b)從apple文檔中,子視圖被添加到自我視圖中,自視圖仍然是工具欄的句柄,所以在dealloc方法中,如果未調用viewDidUnload,工具欄的retainCount不能被縮小爲0.如果內存不足,系統將減少無用的視圖並調用viewDidUnload方法,它會自動將工具欄的retainCount減少爲0.因此,在dealloc方法中,我應該將工具欄設置爲nil。我很困惑,如果我把工具欄設置爲零,當viewDidUnload方法被調用時,工具欄將被縮小或不縮小?有沒有什麼漏洞?

Thx。

+0

但是對於子視圖內存,當子視圖會被釋放釋放時,它應該只調用內存很低且在viewDidUnload方法中? – Golden

+0

儀器測試內存泄漏。檢查這樣的保留計數將告訴你什麼。 – danielbeard

+1

你不應該使用'retainCount':http://stackoverflow.com/questions/11028512/addsubview-and-dealloc-for-memory-leaks-retaincount#comment14420031_11028512 – rckoenes

回答

2

首先,如果你的代碼反映了你真正的代碼,你dealloc方法有一個很大的問題:

- (void) dealloc{ 
    [toolbar removeFromSuperView]; 
    [toolbar release] 
    toolbar = nil; 
} 

你是不是叫[super dealloc]。通過不調用[super dealloc],self.view將永遠不會被釋放(並最終被釋放)。

這應該可以解決您的內存泄漏(部分,至少):

- (void) dealloc{ 
    [toolbar release]; 
    [super dealloc]; 
} 

你可以注意到,我已經刪除了調用removeFromSuperView因爲這是自動爲您完成後self.view實際上是釋放,所以你不需要自己動手。無論如何,撥打removeFromSuperView也不會導致任何問題。

關於您的問題,我認爲您的toolbar屬性被聲明爲retain(根據您提交的代碼,這是對我最感覺的假設)。

如果toolbarretain孩子的財產,那麼正確的方式分配給它一個新創建的看法是:

toolbar = [[[UIToolbar alloc] initWithFrame:nil] autorelease]; 

請注意autorelease;如果不存在,您的保留/發佈呼叫會受到影響。這可以解釋,需要你先打電話release然後nil在dealloc的屬性:

- (void)dealloc { 
... 
    [toolbar release] 
    toolbar = nil; 
.... 
} 

這樣做就像你正在釋放toolbar兩次;但是由於在分配給retain屬性時沒有使用autorelease,這會產生正確的結果。

a)工具欄調用removeFromSuperView和release API,結果是一樣的,工具欄retainCount只會變成1.所以如果我測試代碼只使用它們每一個,結果是一樣的。那麼,我可以總結用戶只能調用每個API嗎?

正如我說的,你不需要直接調用removeFromSuperView得到一個子視圖在dealloc時間被釋放,因爲self.view會爲你做的。當你想移除一個子視圖,同時仍然保持superview(想象你顯示一個標籤然後移除它),這是另一回事。在這種情況下,你需要調用兩者,否則你有泄漏。

b)從蘋果文檔時,子視圖添加到自視圖,自視圖具有保持工具欄手柄,所以在dealloc方法,如果viewDidUnload不叫,工具欄retainCount不能減少到0.如果內存不足,系統將減少無用的視圖並調用viewDidUnload方法,它會自動將工具欄的retainCount減少到0.所以在dealloc方法中,我應該將工具欄設置爲nil。我很困惑,如果我把工具欄設置爲零,當viewDidUnload方法被調用時,工具欄將被縮小或不縮小?有沒有什麼漏洞?

,如果我正確地理解你的疑問,問題是,如果你在viewDidUnload發送toolbar屬性nil,那麼當這個方法被調用(既可以當你明確地刪除視圖或發行時,內存警告)您的子視圖已正確處理;如果你的控制器的dealloc今後被調用,你的財產已經有nil值,所以釋放它不會有任何效果(但這很好,因爲它已經在viewDidUnload中發佈)。另一方面,如果你沒有在viewDidUnload中釋放你的財產,那麼會發生什麼情況是,如果在存儲器警告之後再次顯示視圖,則再次調用loadView/viewDidLoad;否則將會調用loadView/viewDidLoad。但在這種情況下,當您創建工具欄子視圖並將其引用指定給toolbar屬性(假設它爲retain類型)時,則舊對象會自動爲您釋放,因此您不會有任何內存泄漏;會發生什麼是您正在使用更多的內存,因爲您可能會做更多的內存(因爲直到當再次創建self.view時,工具欄纔會被釋放)。

+0

對不起,我霧線超級。 – Golden

+2

您忘記了:「retainCount無用,請勿打電話。」 – bbum

相關問題