添加为subView时,未调用UIViewController viewWillAppear

时间:2013-08-14 15:02:06

标签: ios objective-c uiviewcontroller uiscrollview viewwillappear

我从另一个视图控制器中加载了UIViewController,然后将其视图添加到UIScrollView

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

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

我在统计视图控制器中放置了断点,并且正在调用viewDidLoad,但viewWillAppear不是。

是不是因为我没有将它推到层次结构或其他什么东西?

10 个答案:

答案 0 :(得分:43)

您应该将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

答案 1 :(得分:37)

我再次遇到-viewWillAppear:没有被问到的问题。谷歌搜索后,我来到这里。我做了一些测试,发现-addSubview-addChildViewController:的调用顺序非常重要。

案例1。会触发-viewWillAppear:控制器,但案例2, WON' T 调用{{ 1}}。

案例1:

-viewWillAppear:

案例2:

  controller?.willMoveToParentViewController(self)

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

  controller!.didMoveToParentViewController(self)

答案 2 :(得分:16)

By default, appearance callbacks are automatically forwarded to children. It's determined with shouldAutomaticallyForwardAppearanceMethods property. Check value of this propery, if it's NO and if your child viewController should appear right on container's appearance, you should notify child with following methods in container's controller life-cycle implementation:

- (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];
}

Customizing Appearance and Rotation Callback Behavior

Fixed my problem! Hope it would be helpful.

答案 3 :(得分:4)

如另一个答案中所述,当viewWillAppear设置为shouldAutomaticallyForwardAppearanceMethods时,父视图控制器可能不会调用false等。已知UINavigationControllerUITabBarController可以做到这一点。在这种情况下,您需要在子视图控制器上调用beginAppearanceTransition(_ isAppearing: Bool, animated: Bool),并在视图显示时将isAppearing设置为true,反之亦然。

您必须将这些调用放在代码中的适当位置,通常是在添加和删除子视图控制器时。

自定义转换结束后,别忘了在子视图控制器上调用endAppearanceTransition,否则不会调用viewDidAppearviewDidDisappear

答案 4 :(得分:3)

Per Apple(https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html),添加子视图控制器的API调用的正确顺序是:

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

但是我仍然遇到了孩子VC中的viewWillAppear没有偶尔被调用的问题。我的问题是,在调用容器视图控制器中的 viewDidAppear之前,有一个竞争条件可能导致上面的代码被执行。确保viewDidAppear已被调用(或推迟添加子VC直到它)为我解决了。

答案 5 :(得分:1)

之前的答案是正确的,但如果它有助于某人 - 如果你在子视图控制器中覆盖loadView,则不会调用任何其他UIViewController方法。

我花了一些时间才意识到为什么我的代码没有正常运行,直到我意识到我不小心覆盖了loadView而不是viewDidLoad

答案 6 :(得分:0)

在我的情况下,我发现在我的基础viewWillAppear:类中错误地重写了UINavigationController方法:

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

请注意,我没有致电super.viewWillAppear(animated),而是写了super.viewWillDisappear(animated)

导致此UIViewController内的所有UINavigationController未调用viewWillAppear:方法。

希望能帮助处理类似问题的人。

答案 7 :(得分:0)

检查您的父级 VC是否为 UINavigationViewController (或任何其他容器)。在这种情况下, shouldAutomaticallyForwardAppearanceMethods 应该为 False ,并且不会调用外观方法。

答案 8 :(得分:0)

我无法理解您的问题和描述。 我的问题仅与此类似。

CustomTabBarController-> CustomUINavigationController-> RootViewcontroller

除非您切换到另一个选项卡并返回,否则不会调用CustomUINavigationController和RootViewController的viewWillAppear。

解决方案是调用super.viewWillAppear(animated:true)

override func viewWillAppear(_ animated: Bool) {
    **super.viewWillAppear(true)**
}

我为这个小错误努力了一天多。

答案 9 :(得分:0)

如果您的视图控制器尚未加载其视图,则视图外观方法也不会被转发。如果您在子视图控制器中覆盖 loadView,并且该视图已添加到视图层次结构中,则可能会发生这种情况。

在那种情况下,你可以这样做

addChild(childVC)
childVC.loadViewIfNeeded()
childVC.didMove(toParent: self)