(実際の答えを見つけるのにかなりの掘り下げを要したため、これは質問と回答の両方です。)
症状:viewWillAppear
、viewDidAppear
がUIViewControllerで呼び出されていませんでした。
原因:UINavigationController
またはUITabBarController
(私の場合)をUIViewController
に埋め込むと、これらのメソッドの呼び出しが中断されます。
解決策:前述のUIViewController
/UINavigationController
を含むUITabBarController
で手動で呼び出します。
例(projectNavigationController
がUINavigationController
であると仮定):
void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [projectNavigationController viewWillAppear:animated]; } -(void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [projectNavigationController viewWillDisappear:animated]; } -(void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [projectNavigationController viewDidAppear:animated]; } -(void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; [projectNavigationController viewDidDisappear:animated]; }
私の場合、内部にUITabBarController
があり、それに応じてメソッドを呼び出し、すべて解決しました。
(ソリューションの帰属:---(http://davidebenini.it/2009/01/03/viewwillappear-not-being-called-inside-a-uinavigationcontroller/ )
私は先に進んで@ St3fanに同意せず、反例としてUIKit
を使用します。
ただし、埋め込みコントローラーの一般的な知識(またはその欠如)は、適切なUI設計原則によって導かれる必要があります。
最も簡単な反例は、UINavigationControllers
に埋め込まれたUITabBarControllers
です。これらは至る所に現れます。頭上から、iPhoneのiPodアプリ、iPhoneの電話アプリ内の連絡先。
私はそれらがビューで何をするかをチェックするのに気になるほど興味がありました(「スーパーコントローラー」ビューまたはUIWindow
に追加します。サブコントローラービューがSt3fanの推奨に反する、ビュー階層内のスーパーコントローラービューの子孫。
InterfaceBuilderですべてをフックして2つのタブを持つUITabBarController
ベースのアプリを作成する非常に迅速なiPhoneアプリを作成しました。最初のタブは、プレーンなoleを持つUINavigationController
でしたUIViewController
ルートビューコントローラーであり、2番目のタブが古いUIViewController
であるので、後でクリックする2番目のタブがありました。
いくつかのNSLog
ステートメントを振りかけて、コントローラーのさまざまなUIView's
を出力します。
tabBarController.view = <UILayoutContainerView: 0x5b0dc80; ...
navigationController.view = <UILayoutContainerView: 0x59469a0; ...
rootViewController.view = <UIView: 0x594bb70; ...
Superview: <UIViewControllerWrapperView: 0x594cc90; ...
Superview: <UINavigationTransitionView: 0x594a420; ...
Superview: <UILayoutContainerView: 0x59469a0; ... // navigationController.view
Superview: <UIViewControllerWrapperView: 0x594b430; ...
Superview: <UITransitionView: 0x5b0e110; ...
Superview: <UILayoutContainerView: 0x5b0dc80; ... // tabBarController.view
Superview: <UIWindow: 0x5942a30; ...
「Superview」という接頭辞が付いた行は、rootViewController.view's
のスーパービューチェーンを上に向かってnilに到達するまでの出力です。
次に、もちろん、ルートビューコントローラでviewDidDisappear
が呼び出されるいくつかの場所のコールスタックを一目で確認します。
最初に、新しいコントローラーがスタックにプッシュされた結果として、ルートコントローラーでviewDidDisappear
が呼び出されたときのコールスタック:
-[RootController viewDidDisappear:]
-[UINavigationController navigationTransitionView:didEndTransition:fromView:toView:]
...
次に、一番上のUITabBarControllerで別のタブが選択されたときの呼び出しスタック:
-[RootController viewDidDisappear:]
-[UINavigationController viewDidDisappear:]
-[UITabBarController transitionFromViewController:toViewController:transition:shouldSetSelected:]
したがって、すべての場合において、Appleは、コントローラーが埋め込まれたサブコントローラーのさまざまなviewDidAppear
などのメソッドを呼び出す必要があり、ビューも同様に埋め込まれるべきであると判断しました。 UIKit
デザインをフォローするための良いリードとする場合、OPはこの爪を頭に当てます。
私はこれと同じ状況を見ました。以前は、テーブルセルの選択によってトリガーされたインターフェイスビルダーセグエが機能しなくなりました。コードを少し掘り下げた後、テーブルビューデリゲートのセル選択オーバーライドから呼び出して手動で設定しました。
後で、呼び出されたビューコントローラーでレイアウトを変更しましたが、上記のように、viewDidAppearが呼び出されていないことがわかりました。デバッグ出力は「ネストされたプッシュ操作」などを参照しており、手動のプッシュ操作で自分に大きなコメントがあったため
#warning I SHOULD NOT HAVE TO DO THIS!!
私はセグエコードにブレークポイントを設定しましたが、確かにIBセグエは機能しており、呼び出されたビューでデリゲート呼び出しをめちゃくちゃにしていたのは、テーブルセル選択コードでの手動操作でした。私は手動のコードを削除し、すべてが再び元気です。
ビューがプッシュされた後にセル選択コードが呼び出されるのは奇妙に思えます。呼び出し元で選択したセルのインデックスパスを取得するには、プロトコルとデリゲートを実行する必要があります。