118

viewWillAppearビュー階層を正しく作成していないときに問題を抱えている人々についての投稿を多数読みまし。私の問題は、それが何を意味するのか理解できないことです。

そのコントローラーを作成しRootViewControllerて呼び出すとaddSubView、追加されたビューがイベントに関連付けられることが期待されviewWillAppearます。

viewWillAppearすべてのレベルでイベントを正常に受信する複雑なプログラム ビュー階層の例はありますか?

Apple のドキュメントの状態:

警告: ビュー コントローラーに属するビューがビュー階層に直接追加された場合、ビュー コントローラーはこのメッセージを受け取りません。ビュー階層にビューを挿入または追加し、それにビュー コントローラーがある場合は、関連するビュー コントローラーにこのメッセージを直接送信する必要があります。ビュー コントローラにこのメッセージを送信しないと、関連するアニメーションが表示されなくなります。

問題は、これを行う方法を説明していないことです。"直接" とはどういう意味ですか? ビューを「間接的に」追加するにはどうすればよいですか?

私は Cocoa と iPhone にかなり慣れていないので、基本的な Hello World のがらくた以外に Apple からの有用な例があればいいと思います。

4

27 に答える 27

56

ナビゲーション コントローラーを使用してそのデリゲートを設定すると、view{Will,Did}{Appear,Disappear} メソッドは呼び出されません。

代わりに、ナビゲーション コントローラーのデリゲート メソッドを使用する必要があります。

navigationController:willShowViewController:animated:
navigationController:didShowViewController:animated:
于 2008-10-17T04:35:39.453 に答える
28

私はこれと同じ問題に遭遇しました。viewWillAppearサブビューとして追加する前に、ViewControllerにメッセージを送信するだけです。(表示するようにアニメーション化されているかどうかをView Controllerに通知するBOOLパラメーターが1つあります。)

[myViewController viewWillAppear:NO];

Metronomeの例でRootViewController.mを見てください。

(私は実際にAppleのサンプルプロジェクトが素晴らしいと感じました。HelloWorldよりもたくさんあります;)

于 2008-09-28T01:20:27.820 に答える
18

私は最終的にこれが機能する解決策を見つけました!

UINavigationControllerDelegate

その要点は、ナビゲーションコントロールのデリゲートをそれが含まれているビューコントローラーに設定し、実装することであり、それはUINavigationControllerDelegate2つの方法だと思います。素晴らしい!ついに解決策を見つけたのでとても興奮しています!

于 2010-12-22T10:38:50.490 に答える
9

私はちょうど同じ問題を抱えていました。私のアプリケーションでは、2 つのナビゲーション コントローラーがあり、それぞれに同じビュー コントローラーをプッシュすると、あるケースでは機能し、他のケースでは機能しませんでした。つまり、最初の でまったく同じビュー コントローラーをプッシュするとUINavigationControllerviewWillAppearが呼び出されましたが、2 番目のナビゲーション コントローラーでプッシュしたときには呼び出されませんでした。

次に、この投稿に出くわしましたUINavigationController should call viewWillAppear/viewWillDisappear methods

そして、2 番目のナビゲーション コントローラーが を再定義したことに気付きましたviewWillAppear。コードをスクリーニングすると、私が呼び出していないことがわかりました

[super viewWillAppear:animated];

私はそれを追加しましたが、うまくいきました!

ドキュメントには次のように記載されています。

このメソッドをオーバーライドする場合は、実装のある時点で super を呼び出す必要があります。

于 2010-01-13T14:46:52.903 に答える
5

ナビゲーションコントローラーを使用しています。別のレベルのデータに降りるか、カスタム ビューを表示する場合は、次を使用します。

[self.navigationController pushViewController:<view> animated:<BOOL>];

これを行うと、viewWillAppear関数が起動します。私は実際のaddSubViewメソッドを自分で呼び出していないため、これは「間接的」と見なされると思います。ナビゲーションコントローラーを使用しているかどうかはわからないため、これがアプリケーションに100%適用されるかどうかはわかりませんが、手がかりになるかもしれません.

于 2008-09-25T19:24:01.590 に答える
4

まず、Appleのドキュメントに記載されているように、タブバーはルートレベルにある必要があります。つまり、ウィンドウに追加されている必要があります。これは正しい動作の鍵です。

次に、/を使用して通知を手動で転送できますが、ビュー呼び出しの階層全体を正しく機能させるには、手動で呼び出すだけで済みます。UITabBarDelegateUINavigationBarDelegate

[tabBarController viewWillAppear:NO];
[tabBarController viewDidAppear:NO];

[navBarController viewWillAppear:NO];
[navBarController viewDidAppear:NO];

..それぞれのコントローラーにビューコントローラーを設定する前に1回だけ(割り当て直後)。それ以降、子ViewControllerでこれらのメソッドを正しく呼び出しました。

私の階層は次のようになります。

window
    UITabBarController (subclass of)
        UIViewController (subclass of) // <-- manually calls [navController viewWill/DidAppear
            UINavigationController (subclass of)
                UIViewController (subclass of) // <-- still receives viewWill/Did..etc all the way down from a tab switch at the top of the chain without needing to use ANY delegate methods

tab / navコントローラーで前述のメソッドを初めて呼び出すだけで、すべてのイベントが正しく転送されることが保証されました。UINavigationBarDelegate/UITabBarControllerDelegateメソッドから手動で呼び出す必要がなくなりました。

補足:不思議なことに、それが機能しなかったとき、プライベートメソッド

- (void)transitionFromViewController:(UIViewController*)aFromViewController toViewController:(UIViewController*)aToViewController 

..動作中の実装のコールスタックからわかるように、通常はviewWill/Did..メソッドを呼び出しますが、上記を実行するまで呼び出しませんでした(呼び出された場合でも)。

UITabBarControllerただし、がウィンドウレベルであり、ドキュメントがこれをバックアップしているように見えることが非常に重要だと思います。

それが明確であり、さらなる質問に喜んで答えることを願っています。

于 2011-07-26T17:10:55.653 に答える
3

これを行う正しい方法は、UIViewController コンテインメント API を使用することです。

- (void)viewDidLoad {
     [super viewDidLoad];
     // Do any additional setup after loading the view.
     UIViewController *viewController = ...;
     [self addChildViewController:viewController];
     [self.view addSubview:viewController.view];
     [viewController didMoveToParentViewController:self];
}
于 2015-07-28T16:47:06.977 に答える
3

ビューは、 を呼び出すことによって「直接」追加され[view addSubview:subview]ます。ビューは、サブビューを交換するタブ バーやナビゲーション バーなどの方法によって「間接的に」追加されます。

に電話するときはいつでも[view addSubview:subviewController.view]、電話する必要があります[subviewController viewWillAppear:NO](または場合によっては YES になります)。

ゲームのサブスクリーン用に独自のカスタム ルート ビュー管理システムを実装したときに、この問題が発生しました。viewWillAppear への呼び出しを手動で追加すると、問題が解決しました。

于 2010-11-22T03:21:13.770 に答える
3

答えは受け入れられず、人々は(私がしたように)ここに着陸するので、私は私のバリエーションを与えます. それが元の問題だったかどうかはわかりませんが。ナビゲーション コントローラーがサブビューとして別のビューに追加される場合、viewWillAppear/Dissappear などのメソッドを自分で次のように呼び出す必要があります。

- (void) viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    [subNavCntlr viewWillAppear:animated];
}

- (void) viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    [subNavCntlr viewWillDisappear:animated];
}

例を完成させるためだけに。このコードは、ビューに配置したビューにナビゲーション コントローラーを作成して追加した ViewController に表示されます。

- (void)viewDidLoad {

    // This is the root View Controller
    rootTable *rootTableController = [[rootTable alloc]
                 initWithStyle:UITableViewStyleGrouped];

    subNavCntlr = [[UINavigationController alloc]   
                  initWithRootViewController:rootTableController];

    [rootTableController release];

    subNavCntlr.view.frame = subNavContainer.bounds;

    [subNavContainer addSubview:subNavCntlr.view];

    [super viewDidLoad];
}

.h は次のようになります

@interface navTestViewController : UIViewController <UINavigationControllerDelegate> {
    IBOutlet UIView *subNavContainer;
    UINavigationController *subNavCntlr;
}

@end

nib ファイルにはビューがあり、このビューの下には、コントローラーを配置するイメージとコンテナー (別のビュー) のラベルがあります。これがどのように見えるかです。これはクライアントの仕事だったので、いくつかのことをごちゃまぜにしなければなりませんでした。

代替テキスト

于 2010-12-04T20:53:42.580 に答える
2

非常によくある間違いは次のとおりです。1 つのビュー とUIView* a、もう 1つのビュー がありUIView* bます。b をサブビューとして a に追加します。b で viewWillAppear を呼び出そうとしても、a のサブビューであるため、起動されません。

于 2013-12-05T14:05:07.733 に答える
2

ビューコントローラーのプッシュとポップに次のコードを使用します。

押す:

[self.navigationController pushViewController:detaiViewController animated:YES];
[detailNewsViewController viewWillAppear:YES];

ポップ:

[[self.navigationController popViewControllerAnimated:YES] viewWillAppear:YES];

..そしてそれは私にとってはうまくいきます。

于 2012-06-22T07:57:17.090 に答える
2

iOS 13 は、ここで私のアプリをお尻に入れました。iOS 13 の時点で動作の変更に気付いた場合は、プッシュする前に次のように設定してください。

yourVC.modalPresentationStyle = UIModalPresentationFullScreen;

また、属性インスペクターの .storyboard に設定する必要がある場合もあります (プレゼンテーションをフルスクリーンに設定します)。

これにより、アプリは以前のバージョンの iOS と同じように動作します。

于 2019-10-16T14:49:55.727 に答える
1

これについて100%確信はありませんが、ビュー階層にビューを追加することは、新しいビューコントローラーをナビゲーションコントローラーのスタックにプッシュするのではなく-addSubview:、ビューコントローラーのビュー(たとえば)を呼び出すことを直接意味すると思います。[viewController.view addSubview:anotherViewController.view]

于 2008-10-07T15:51:46.657 に答える
1

これが誰かを助ける場合に備えて。ViewWillAppearで発砲しないという同様の問題がありましたUITableViewController。何度も遊んだ後、問題はUINavigationController自分をコントロールしてUITableViewいるのがルートビューにないことだと気づきました。それを修正すると、今ではチャンピオンのように機能しています。

于 2010-11-19T20:18:26.057 に答える
1

私はちょうどこの問題を自分で抱えていて、それを修正するのに 3 時間 (うち 2 時間はグーグル検索) かかりました。

役立つことが判明したのは、デバイス/シミュレーターからアプリを削除し、クリーンアップしてから再度実行することでした。

それが役立つことを願っています

于 2013-09-21T18:18:19.980 に答える
1
[self.navigationController setDelegate:self];

デリゲートをルート ビュー コントローラーに設定します。

于 2010-11-23T13:36:12.533 に答える
1

サブビューを追加しても必ずしもビューが表示されるとは限らないと思うので、それが表示されるクラスのメソッドへの自動呼び出しはありません

于 2009-05-25T06:05:42.133 に答える
1

「直接」とは、xcode の「Navigation Application」テンプレートと同じように接続することであり、UINavigationController をアプリケーションの UIWindow の唯一のサブビューとして設定します。

そのテンプレートを使用することが、UINavigationController でこれらのコントローラーのプッシュ/ポップ時にオブジェクト ViewControllers で呼び出される Will/Did/Appear/Disappear メソッドを取得できる唯一の方法です。ここでの回答の他のソリューションは、RootController に実装して (子) NavigationController に渡すなど、私にとってはうまくいきませんでした。これらの関数 (will/did/appear/disappear) は、ナビゲーション コントローラーのサブ VC ではなく、最上位の VC、「ログイン」およびナビゲーション VC を表示/非表示にするときに RootController でのみ呼び出されたので、それを行う機会がありませんでした。 Nav VC に「パススルー」します。

最終的に、UINavigationController のデリゲート機能を使用して、アプリでフォローアップ機能を必要とする特定のトランジションを探しましたが、それは機能しますが、消える機能と表示される機能の両方を「シミュレート」するには、もう少し作業が必要です。

また、今日この問題に何時間も頭を悩ませた後、それを機能させることも原則の問題です。カスタム RootController と子ナビゲーション VC を使用した動作するコード スニペットは大歓迎です。

于 2010-06-15T15:50:25.783 に答える
-2

これが私が解決した問題と同じかどうかはわかりません。
「[self methodOne]」など、通常の方法ではメソッドが実行されない場合があります。

試す

- (void)viewWillAppear:(BOOL)animated
{
    [self performSelector:@selector(methodOne) 
           withObject:nil afterDelay:0];
}
于 2011-11-16T19:35:51.517 に答える
-3

常に 1 つの UIViewController のみをアクティブにする必要があります。操作したいサブビューはすべて、サブビュー、つまり UIView である必要があります。

ビュー階層を管理するために単純な手法を使用していますが、この方法で作業を開始して以来、まだ問題に遭遇していません。重要なポイントは 2 つあります。

  • アプリの「画面の価値」を管理するには、単一の UIViewController を使用する必要があります
  • ビューの変更に UINavigationController を使用する

「画面の価値」とはどういう意味ですか? 意図的に少しあいまいですが、一般的にはアプリの機能またはセクションです。背景画像が同じでオーバーレイ/ポップアップなどが異なる画面がいくつかある場合、それは 1 つのビュー コントローラーと複数の子ビューである必要があります。2 つのビュー コントローラーを使用することは決してないはずです。画面の特定の領域を複数のView Controllerで表示したい場合は、1つのView ControllerでUIViewをインスタンス化し、それを別のView Controllerのサブビューとして追加できることに注意してください。

UINavigationController に関しては - これはあなたの親友です! ナビゲーション バーをオフにして、アニメーションに NO を指定すると、必要に応じて画面を切り替える優れた方法が得られます。ビュー コントローラが階層内にある場合はプッシュおよびポップできます。または、ビュー コントローラの配列 (単一の VC を含む配列を含む) を準備し、setViewControllers を使用してそれをビュー スタックに設定することもできます。これにより、VC を自由に変更できると同時に、Apple の想定モデル内で動作し、すべてのイベントなどを適切に起動するというすべての利点が得られます。

アプリを起動するたびに行うことは次のとおりです。

  • ウィンドウベースのアプリから開始
  • ウィンドウの rootViewController として UINavigationController を追加します
  • navコントローラーのrootViewControllerとして最初のUIViewControllerにしたいものを追加します

(ウィンドウベースから始めることは個人的な好みにすぎないことに注意してください。私は自分で物事を構築するのが好きなので、それらがどのように構築されているかを正確に知っています。ビューベースのテンプレートでうまく動作するはずです)

すべてのイベントが正しく発生し、基本的には問題ありません。これにより、アプリの重要な部分を記述することにすべての時間を費やすことができ、ビュー階層を手動でハックして形を整えようとすることに時間を費やすことができます。

于 2011-09-17T11:05:02.700 に答える