2009-06-02 9 views
12

私はそうでないことを示唆しているような状況に遭遇しました。次のコードでは、self.navigationController = navという行を削除すると、ルートコントローラのビューが表示されず、addSubviewが他の方法で実際にビューを保持しない可能性があることを示しています。何か案が?UIViewのaddSubviewは本当にビューを保持していますか?

- (void)applicationDidFinishLaunching:(UIApplication *)application { 
    self.testViewController = [[TestViewController alloc] initWithNibName:@"TestView" bundle: [NSBundle mainBundle]]; 

    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:self.testViewController]; 

    self.navigationController = nav; //<-- if this line is removed, test view won't show up 

    [window addSubview:nav.view]; 

    [nav release]; 
} 
+0

あなたのマークされた回答は正しくありません。理由は以下のとおりです。 –

答えて

24

このライン:

[window addSubview:nav.view]; 

はすぐに画面に表示を追加しません。おそらく異なるスレッド上の将来の実行ループにOSによって表示されます。実際の実装ではわかりません。

これは、AppleがviewDidAppear/viewWillAppearのようなデリゲートメソッドを定義する理由です。そうしないと、これらのイベントがいつ発生するか正確に知ることができません。

また、あなたが言ったようにサブビューを追加すると、実際にはビューが保持されます。 ただし、ビューコントローラまたはナビゲーションコントローラは保持します。ナビゲーションコントローラWILLには、追加されたView Controllerがすべて保持されているので、ivarで戻す必要はありません。

しかし、ナビゲーションコントローラへの参照は、メソッドの範囲を超えてを保持する必要があります。あなたのコードに応じて、それは解放されるか、参照が失われる可能性があります。

ですから、IVARとナビゲーションコントローラへの参照を保持し、そのようにそれを設定する必要があります。

self.navigationController = nav; 

のでnav.viewがtestViewController.viewへのポインタを含んでいても、アプリケーションは何の言及がありませんナビゲーションコントローラー、および、拡張ビューによって表示されます。結果は空白の画面になります。あなたが実際に次のような方法でリークしている


それが保持/解放の問題ではないこと、これはより明白にするために、:

self.testViewController = [[TestViewController alloc] initWithNibName:@"TestView" bundle: [NSBundle mainBundle]]; 

あなたが保持/リリースのバランスを取るために自動解放する必要がありますby:

self.testViewController = [[[TestViewController alloc] initWithNibName:@"TestView" bundle: [NSBundle mainBundle]] autorelease]; 

これは、このコードを実行したときにビューが決して割り当て解除されなかったことを意味します。あなたの問題は確かに失われた参照であることがさらに保証されます。

+0

素敵な仕事コーリー、あなたが描いた説明が本当に好きです。 – Boon

+1

_view_がウィンドウを保持する前に割り当て解除されることは間違っています。その場合、ウィンドウが解放されたオブジェクトにアクセスしようとすると例外が発生します。割り振り解除されるのは、ナビゲーション・コントローラーです。ナビゲーション・コントローラーは、(ナビゲーション・バーやルート・ビューのような)興味深いコンテンツをビューに取り込まないようにします。 –

+0

それについてもっと考えてみたら、あなたが見るものを説明するのに役立ついくつかの追加情報を追加しました。 –

0

これは私には保持/解放の質問ではありません。 self.navigationController = nav;をコメントアウトすると表示されません。なぜなら、次の行にある[window addSubview:self.navigationController.view]のself.navigationControllerプロパティが設定されないからです。それはおそらく無かったり、クラッシュするかもしれませんが、コードを増やすことなく確実に言うことはできません。

+0

私は、コードが正常に動作しなかったときに元のコードに更新し、navへの参照を保持するためにself.navigationControllerを導入しなければなりませんでした。また、上に表示されているのは、そこにあるすべてのコードだけです。 – Boon

+0

objective-cでは、ivarsは値0で始まります。したがって、self.navigationControllerはnilになります。 –

2

問題はおそらく、ビューが保持されていないということではなく、コントローラが保持されていないということです。この行がなければ

self.navigationController = nav 

何もナビゲーションコントローラを保持されません。コントローラーの寿命を延ばすことは奇妙です。

+0

ビューはビューコントローラに「魔法のように」結ばれていません。ビューは、ビューコントローラが消滅したために死ぬだけではありません。ビューが他の場所に保持されている場合は、ビューコントローラーよりも長持ちします。 –

+0

私はそれが起こらないとは言わなかった。私は、他の人より長く生きるのは奇妙だと言った。特に、ビューがナビゲーションコントローラのビューである場合、これはナビゲーションコントローラによってコンシュームされた内部ビュー階層です。 –

+0

あなたがコンベンションに従えば、あなたは正しいです。私の唯一のポイントは、それ自体の理由ではないということです。 これは、ビュー階層からそのビューを削除する前に、一般にビューコントローラを解放しないためです。しかし、UIViewControllerには、これを行わない仕組みがありません。これは、適切なメモリ管理の習慣にすぎません。 –

関連する問題