web-dev-qa-db-ja.com

subViewとして追加するときにUIViewController viewWillAppearが呼び出されない

別のView Controller内から読み込んで_UIViewControllerにビューを追加するUIScrollViewがあります。

self.statisticsController = [self.storyboard instantiateViewControllerWithIdentifier:@"StatisticsViewController"];
self.statisticsController.match = self.match;

[self.scrollView addSubview:self.statisticsController.view];

統計ビューコントローラーにブレークポイントを配置し、viewDidLoadが呼び出されていますが、viewWillAppearは呼び出されていません。

それは私がそれを階層などにプッシュしていないからですか?

24
Fogmeister

ビューを追加するコントローラーの子ビューコントローラーとしてstatisticsControllerを追加する必要があります。

self.statisticsController = [self.storyboard instantiateViewControllerWithIdentifier:@"StatisticsViewController"];
self.statisticsController.match = self.match;

[self.scrollView addSubview:self.statisticsController.view];
[self addChildViewController:self.statisticsController];
[self.statisticsController didMoveToParentViewController:self];

これによってviewDidAppearが呼び出されるかどうかはわかりませんが、didMoveToParentViewController:が子コントローラーで呼び出され、それが呼び出されるため、viewDidAppearに入れたコードをそこに入れることができます。

44
rdelmar

-viewWillAppear:再び問題と呼ばれることはありません。グーグルの後、私はここに来ました。いくつかのテストを行ったところ、-addSubviewおよび-addChildViewController: は重要。

ケース1。トリガー-viewWillAppear:が、コントローラケース2 it WO N'T call -viewWillAppear:

事例1:

  controller?.willMoveToParentViewController(self)

  // Call addSubview first
  self.scrollView.addSubview(controller!.view)
  self.addChildViewController(controller!)

  controller!.didMoveToParentViewController(self)

事例2:

  controller?.willMoveToParentViewController(self)

  // Call adChildViewController first      
  self.addChildViewController(controller!)      
  self.scrollView.addSubview(controller!.view)

  controller!.didMoveToParentViewController(self)
40
AechoLiu

デフォルトでは、外観コールバックは自動的に子に転送されます。 shouldAutomaticallyForwardAppearanceMethodsプロパティで決定されます。このプロパティの値をチェックします。[〜#〜] no [〜#〜]で、子のviewControllerがコンテナの外観に正しく表示される場合は、コンテナのコントローラライフサイクル実装で次のメソッドを使用して子に通知する必要があります。

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    for (UIViewController *child in self.childViewControllers) {
        [child beginAppearanceTransition:YES animated:animated];
    }
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self.child endAppearanceTransition];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    for (UIViewController *child in self.childViewControllers) {
        [child beginAppearanceTransition:NO animated:animated];
    }
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    [self.child endAppearanceTransition];
}

外観と回転のコールバック動作のカスタマイズ

私の問題を修正しました!それが役に立てば幸いです。

16

別の回答で述べたように、viewWillAppearshouldAutomaticallyForwardAppearanceMethodsに設定されている場合、親View Controllerはfalseなどを呼び出さない場合があります。 UINavigationControllerUITabBarControllerがそうすることが知られています。この場合、ビューが表示されるときにisAppearingtrueに設定して、子View ControllerでbeginAppearanceTransition(_ isAppearing: Bool, animated: Bool)を呼び出す必要があります。

通常、子View Controllerを追加および削除するときに、コード内の適切な場所にこれらの呼び出しを配置する必要があります。

カスタムトランジションが終了したら、子View ControllerでendAppearanceTransitionを呼び出すことを忘れないでください。そうでない場合、viewDidAppearviewDidDisappearは呼び出されません。

4
bompf

Per Apple( https://developer.Apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html )、追加するAPI呼び出しの正しい順序子View Controllerは次のとおりです。

[self addChildViewController:childVC];
[self.view addSubview:childVC.view];
[childVC didMoveToParentViewController:self];

しかし、子供のviewWillAppear VCが時々呼び出されないという問題がありました。私の問題は、上記のコードが実行される原因となる競合状態があったことですbeforeコンテナView ControllerのviewDidAppearが呼び出されました。viewDidAppearが既に呼び出されていることを確認します(または、子の追加を延期しますVCだった)私のためにそれを解決しました。

3
gumbypp

前の答えは正しいですが、誰かに役立つ場合-子View ControllerでloadViewをオーバーライドすると、他のUIViewControllerメソッドは呼び出されません。

誤ってloadViewの代わりにviewDidLoadをオーバーライドしたことに気付くまで、コードが正しく実行されなかった理由を理解するためにしばらく時間がかかりました。

1
Liron

私の場合、ベースUINavigationControllerクラスの_viewWillAppear:_メソッドを誤って書き換えていることがわかりました。

_override func viewWillAppear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    // other stuff
}
_

super.viewWillAppear(animated)を呼び出す代わりに、super.viewWillDisappear(animated)を作成したことに注意してください。

そのため、このUIViewController内にあるUINavigationControllerのすべてが_viewWillAppear:_メソッドを呼び出していませんでした。

同様の問題で誰かを助けることを願っています。

0