【问题标题】:UIViewController viewWillAppear not called when adding as subView添加为子视图时未调用 UIViewController viewWillAppear
【发布时间】:2013-08-16 14:45:56
【问题描述】:

我有一个UIViewController,我正在从另一个视图控制器内部加载它,然后将其视图添加到UIScrollView。

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

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

我在统计视图控制器中设置了断点,viewDidLoad 被调用但viewWillAppear 没有被调用。

是因为我没有把它推到层次结构上还是什么?

【问题讨论】:

标签: ios objective-c uiviewcontroller uiscrollview viewwillappear


【解决方案1】:

您应该将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在那里。

【讨论】:

  • 这会触发 viewDidAppear 方法吗?
  • 嘿!这有效 :D 非常感谢! @sbarow 是的,它触发 viewWillAppear 方法。
  • 这仅适用于 iOS 6,在 iOS 5 上您必须手动调用 viewWillAppear:。
  • 在 [self addChildViewController:self.statisticsController] 之前应该有 [self.statisticsController willMoveToParentViewController:self] 调用。
  • 其实你必须先addChildViewController,然后addSubview。
【解决方案2】:

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

案例 1. 将触发控制器的 -viewWillAppear:,但 案例 2, 它不会 调用 -viewWillAppear:。

案例一:

  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)

【讨论】:

  • 有趣。这与 Apple 在视图控制器编程指南中的文档相矛盾。你应该提交一个错误。
  • 这对我有帮助。
  • 这有什么更新吗?对我来说似乎是一个错误,但肯定遇到了同样的事情。 Apple 的文档指出案例 2 是正确的方法,而且更有意义 (developer.apple.com/library/content/featuredarticles/…)。也许我会提交雷达...
  • @SeeMeCode,请提交雷达。 :) 我已经有 1 年没有碰过这些代码了。
  • 我可以补充一点,这个错误发生在我们的 iOS 10 上。后来在 iOS 11 上运行良好。
【解决方案3】:

默认情况下,外观回调会自动转发给子级。 它由 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];
}

Customizing Appearance and Rotation Callback Behavior

解决了我的问题!希望它会有所帮助。

【讨论】:

    【解决方案4】:

    正如另一个答案中提到的,当shouldAutomaticallyForwardAppearanceMethods 设置为false 时,父视图控制器可能不会调用viewWillAppear 等。众所周知,UINavigationController 和 UITabBarController 会这样做。在这种情况下,您需要在视图出现时调用子视图控制器上的beginAppearanceTransition(_ isAppearing: Bool, animated: Bool),并将isAppearing 设置为true,反之亦然。

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

    当您的自定义转换结束时,不要忘记在您的子视图控制器上调用endAppearanceTransition,否则不会调用viewDidAppear 和viewDidDisappear。

    【讨论】:

      【解决方案5】:

      根据 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 没有偶尔被调用。我的问题是有一个竞争条件可能导致上面的代码在容器视图控制器被调用之前执行 before viewDidAppear。确保 viewDidAppear 已经被调用(或推迟添加子 VC 直到它被调用)为我解决了这个问题。

      【讨论】:

        【解决方案6】:

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

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

        【讨论】:

          【解决方案7】:

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

          【讨论】:

            【解决方案8】:

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

            CustomTabBarController -> CustomUINavigationController -> RootViewcontroller

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

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

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

            我为这个小错误挣扎了一天多。

            【讨论】:

              【解决方案9】:

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

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

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

              【讨论】:

                猜你喜欢
                • 2014-09-05
                • 1970-01-01
                • 2013-04-21
                • 2010-12-01
                • 2011-09-14
                • 1970-01-01
                • 2015-02-21
                • 2017-01-26
                • 1970-01-01
                相关资源
                最近更新 更多