2012-01-05 77 views
4

我有一個使用ARC的iOS應用程序。我不使用InterfaceBuilder,所有UI都是手動生成的。在那個應用程序中,我有幾個UIViewController與SubViewControllers。那些ViewController由一個菜單(-ViewController)綁定在一起,並將它們推送到堆棧上。未在ios視圖層次結構中發佈的內存

我的問題是,在ViewControllers之間切換時,內存不會被釋放。

保持對像這樣的SubViewControllers的引用是錯誤的嗎?

@property (nonatomic, strong) UIViewController subViewController1; 
@property (nonatomic, strong) UIViewController subViewController2; 

viewDidUnload不會被調用。有沒有人有一個很好的例子如何建立一個乾淨的視圖層次?

+0

viewDidUnload只能在內存不足的情況下調用 – 0x8badf00d 2012-01-05 23:27:28

回答

0

這很可能與ARC無關。當視圖屬性被釋放/設置爲零時,viewDidUnload僅在視圖控制器上被調用,並且這通常僅在應用程序收到內存警告時纔會發生。

嘗試觸發模擬器中的內存警告,看看是否會導致您的viewDidUnload方法觸發。如果確實如此,那麼一切都很好。如果沒有,你可能會過度保留你的觀點,或許將它們分配給其他強保留的屬性。

視圖保留策略也有例外情況,例如UINavigationController在視圖控制器堆棧中釋放視圖(如果它們不是最前面的),但只要將它的子控制器的視圖設置爲零'被另一位管理員的觀點所覆蓋。

如果您希望在不在屏幕上時發佈視圖,可以將viewDidDisappear:方法中控制器的視圖屬性設置爲零,或在視圖不在屏幕上時停止保留視圖控制器,只創建新的視圖控制器實例每次你需要顯示它們(這樣,控制器和視圖將在不使用時被釋放)。

5

通過將在堆棧上推送的視圖控制器分配給強實例變量/屬性,從堆棧彈出時不會釋放它們。即使在彈出堆棧之後,強大的屬性仍然保留在推送的視圖控制器上,因此它們永遠不會達到可以被釋放的狀態。

通常我做這樣的事情的推動下一級向下視圖控制器時到導航堆棧如下:

SLSMoleculeSearchViewController *searchViewController = [[SLSMoleculeSearchViewController alloc] initWithStyle:UITableViewStylePlain]; 
[self.navigationController pushViewController:searchViewController animated:YES]; 

根據ARC,新的視圖控制器將被分配,並會在創建保留。當被推入導航堆棧時,它將被導航控制器保留一次。因爲這個新的視圖控制器在被推入後沒有被引用,並且沒有被分配給強屬性或實例變量,所以ARC將在第二行之後釋放它。

請記住,它仍然被導航控制器保留,所以它仍然在內存中。但是,一旦導航控制器將其從堆棧中彈出,該視圖控制器將被釋放。由於此時沒有任何東西可以繼續使用,因此將按預期方式將其解除分配。

如果由於某種原因需要在上級視圖控制器中維護對此子視圖控制器的引用,則可以使用weak屬性或__weak實例變量。這不會影響視圖控制器,一旦控制器被釋放,它將變爲零。

weakweak引用僅支持針對iOS 5.0的應用程序,因此您無法在iOS 4.0上運行任何需要的引用。由於指向釋放內存的指針的危險,4.0兼容的unsafe_unretained屬性並不是我在這種情況下推薦的。

+0

非常感謝,澄清了我對如何創建視圖控制器以儘快釋放它們的懷疑! – spamoom 2013-02-06 20:39:23