2009-07-21 118 views

回答

51

除了已經指出的內容之外,我想詳細說明-viewDidUnload背後的邏輯。

實現它的一個最重要的原因是UIViewController子類通常還包含對視圖層次結構中各種子視圖的擁有引用。例如,在從筆尖加載時,可以通過IBOutlets設置這些屬性,或者在-loadView內以編程方式設置這些屬性。

UIViewController對子視圖的附加所有權意味着,即使其視圖從視圖層次結構中刪除並釋放以節省內存,視圖也會釋放子視圖,但實際上它們不會被釋放,因爲UIViewController本身仍然包含其對這些對象的優秀保留引用。釋放這些對象的附加所有權可確保它們也將被釋放以釋放內存。

當您在此處發佈的對象通常是在UIViewController視圖爲re-loaded時(通過Nib或-loadView的實現)重新創建並重新設置。

另請注意,在調用此方法時,UIViewControllerview屬性爲nil

21

作爲documentation says

它在低存儲器條件下,當視圖控制器需要釋放其視圖與視圖以釋放內存相關聯的任何對象調用。

在相同的情況下dealloc調用。此方法僅在OS3及更高版本中可用。處理iPhone OS 2.x中的相同情況真是痛苦!

更新2015年7月:「視圖是低內存情況下不再清除,因此該方法不會被調用」應該注意的是,viewDidUnload在iOS 6的反對,因爲所以,現代的建議是不要擔心它,並使用dealloc

+6

同樣來自於文檔:「您應該只爲稍後可以輕鬆重新創建的對象執行此操作,無論是在viewDidLoad方法中還是從應用程序的其他部分執行此操作,都不應該使用此方法釋放用戶數據或任何其他信息不容易重新創建「。這也是我自己的問題,謝謝! – leolobato 2009-07-21 12:52:02

+0

如果視圖當前可見,該怎麼辦?由於低內存警告,放棄它不會不好嗎? ;)那麼應用程序將只是空白。由於內存不足,我無法釋放視圖。如果我沒有看到視圖,我總是釋放整個控制器。 Althogh我有一個根視圖控制器保持完好,並管理它的子視圖控制器的所有加載/卸載... – Thanks 2009-07-21 18:37:59

+0

不,你不會使用這個,如果你只是交換一個視圖爲另一個。想想你有一個UINavigationController的「堆棧」視圖的情況。只有一個視圖可見,並且如果您有內存警告,則可以釋放所有不可見的視圖。 – 2009-07-21 20:20:30

3

您可以釋放任何子視圖,例如保留在loadView方法中的UIImageView,或者更好的是該UIImageView上的圖像。

8

請記住,viewDidUnload是視圖控制器中的方法,而不是視圖中的方法。方法將在視圖卸載時調用,但視圖控制器的方法可能會在稍後才能調用。

如果您得到的內存警告不足,並且您的視圖沒有顯示,例如在您使用UIImagePickerController讓用戶拍攝照片時會發生這種情況,您的視圖將被卸載並需要重新加載之後。

6

結論:

視圖控制器有一個視圖屬性。通常,一個筆尖或一段代碼會將其他視圖添加到此視圖。這通常發生在一個-viewDidLoad方法裏面,像這樣:

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    [self createManyViewsAndAddThemToSelfDotView]; 
} 

此外,筆尖文件可能會創建一個按鈕,並將其附加到視圖控制器的看法。

在iPhone OS 2.2上,當從系統調用-dReReiveMemoryWarning時,必須釋放一些內容才能釋放內存。如果有意義的話,你可以釋放整個視圖控制器的視圖。或者只是大容量的內存消耗。現在

- (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview 
    // Release anything that's not essential, such as cached data 
} 

,在新的OS 3.0,還有一個-viewDidUnload方法,它會從當視圖已經因爲低內存中卸載的系統調用(請糾正我:當究竟這個被調用?)

-viewDidUnload用於釋放由視圖控制器本身和視圖同時擁有的所有對象。原因是:如果視圖控制器持有對視圖的子視圖的引用,即按鈕,則引用的子視圖將不會被釋放,因爲它們的保留計數大於等於1.在它們在-viewDidUnload中釋放後,它們可以釋放從記憶裏。

9

這是因爲你通常會設置@property"(nonatomic, retain)",因此這將會爲您創建的setter釋放當前的對象,然後保留即

self.property = nil; 

參數...確實沿着線的東西的:

[property release]; 
property = [nil retain]; 

因此你殺二鳥一石:內存管理(釋放現有對象)並分配指針零(因爲發送任何消息到零指針將返回nil)。

希望有所幫助。

5

如果視圖控制器從導航控制器堆棧中彈出並且沒有保留在其他任何地方,它將被釋放,並且將調用dealloc而不是viewDidUnload。您應該釋放在dealloc中loadView中創建的視圖,但不需要將變量設置爲零,因爲在調用dealloc之後不久,變量將不再存在。

6

蘋果棄用的viewWillUnload,現在你應該使用didReceiveMemoryWarning或dealloc來釋放你的objetcs。

在iOS 6中,現在不推薦使用viewWillUnload和viewDidUnload方法 UIViewController。如果您使用這些方法 來發布數據,請改爲使用didReceiveMemoryWarning方法。您也可以使用此方法在控制器未使用的情況下釋放對視圖控制器視圖的引用。在執行此操作之前,您需要測試該視圖不在窗口中的 。

相關問題