2014-02-22 84 views
7

情況:有推送UIViewController的UINavigationController。爲什麼在UINavigationController和UIViewControllers之間沒有保留循環

1.UIViewController具有的UINavigationController

強參考
@property(nonatomic,readonly,retain) UINavigationController *navigationController 

2.UINavigationController存儲的NSArray

@property(nonatomic,copy) NSArray *viewControllers; 

UINavigationController的視圖控制器應該有強引用本NSArray的(或將被重新分配)。

3.NSArray對包含的視圖控制器有很強的參考。

UPDATE: 讓我們在代碼某處想象,我們有以下:

UIViewController *A = [ [UIViewController alloc] init ]; 
UINavigationController *B = [ [ UINavigationController alloc ] initWithRootViewController:A ]; 
// Here we have strong reference in A to B, in B to B.viewControllers (count == 1) and in B.viewControllers to A. 
// Local variable's strong references to A and B 
A = nil; B = nil; 
// Local variable's strong references has gone 
// But we should still have retain loop here 
// Magic !?? :) 

我的問題是,爲什麼我們沒有在這裏保留循環?

+0

只有當處於堆棧中的viewControllers時,您的觀點3纔是真實的。當ViewController被移除(解散)時,它不再是真的。 –

+0

請參閱我的示例(下面的更新)哪裏查看控制器彈出? – Avt

+0

這裏有一個循環,但是因爲它可以被破壞,所以這不是問題。並非所有的參考循環都是問題。你的代碼片段不會改變文森特的答案。 –

回答

13

2.UINavigationController存儲在NSArray

即是不是一個給定的視圖控制器。

@property(nonatomic,copy) NSArray *viewControllers; 

這決不表示有一個叫做_viewControllers的ivar或類似的東西。它只是告訴我們,有一些方法-viewControllers,將返回我們NSArray,並且有一些方法setViewControllers:將接受一個,並暗示它會做一個副本(或至少表現得像它做了副本它)。這是全部它告訴我們。如果在調試器中擴展NSNavigationController,則會注意到在那裏沒有列出伊娃。

如果你稍微摸索一下,你會發現-viewControllers沒有作爲綜合屬性實現。它只轉發到-childViewControllers(這是一個UIViewController屬性)。好的,那麼這不就是解決問題嗎?我的意思是-childViewControllers實現爲[NSArray arrayWithArray:_childViewControllers]。很公平。你抓到我了。

但是相同的邏輯適用於[UIViewController navigationController]。此聲明:

@property(nonatomic,readonly,retain) UINavigationController *navigationController 

並不意味着它實際上具有強大的聯繫。這隻意味着如果你撥打setNavigationController:,你會期望它保留它。但是你不能撥打setNavigationController:。沒有這樣的方法(甚至沒有私人的方法)。所以這一切真的很有希望,有一種方法叫做-navigationController。並且它的實現爲對+[UINavigationController _ancestorViewControllerOfClass:allowModalParent:]的調用。這只是傳遞到UIViewController實現,該實現在parentViewController鏈中尋找UINavigationController。所以沒有保留循環;它是動態確定的。

但你的問題仍然是一個很好的問題。這裏的頭文件讓IMO感到困惑,我會開一個雷達來對付它。 navigationController應該被列爲assign,或者它應該什麼也不說(即使默認爲strong它至少不會有誤導性)。

順便說一句,如果這東西讓你感興趣,你真的應該爲Hopper減掉90美元。這種探索非常擅長。

+0

謝謝你的回答和Hopper鏈接。 – Avt

+0

感謝Hopper鏈接Rob。如果你有一篇關於你使用的電子工具的文章 - 你會分享它嗎?一般來說,瞭解一個主人的工具是非常非常有趣的(在這裏不要接吻)。乾杯! – user1244109

+0

90%的逆向工程工作是Hopper,nm,otool和字符串(以及Mac上的F-script,儘管最近這種工作對我而言並不奏效)。我過去常常使用類轉儲,但是我一直無法找到適用於現代應用程序的良好替代品。但我不認真對待逆向工程;例如,我幾乎從不嘗試開放一個App Store應用程序(任何嚴肅的瀏覽器經常會這樣做)。 –

2

UINavigationControllerviewControllers屬性被定義爲

@property(nonatomic, copy) NSArray *viewControllers 

導航堆棧上的當前視圖控制器。

然後,沒有問題的保留循環,因爲導航控制器在視圖控制器關閉時從該數組中刪除任何UIViewController

一個保留環路(使用release如果非ARC,或強屬性設置爲nil)一個問題,當你沒有任何機制在某些時候釋放保留的對象打開循環。

+0

請閱讀更新。 – Avt

+0

視圖控制器在我的示例中被解僱了嗎?沒有指令'B.viewControllers = [NSArray ...]'沒有'[B popViewController]'否'[B popToRootViewController]'。被解僱的地方? – Avt

+1

問題不在於解僱。問題是,如果A保留B和B保留A,那麼A和B如何不存在_當沒有其他引用時__。 – matt

相關問題