31

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

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

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

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

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

4

9 回答 9

52

您应该将其添加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其中。

于 2013-08-14T15:08:14.827 回答
46

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

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

情况1:

  controller?.willMoveToParentViewController(self)

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

  controller!.didMoveToParentViewController(self)

案例二:

  controller?.willMoveToParentViewController(self)

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

  controller!.didMoveToParentViewController(self)
于 2016-08-26T07:46:16.567 回答
22

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

自定义外观和旋转回调行为

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

于 2015-06-26T09:44:55.840 回答
6

正如另一个答案中提到的,当设置为. 时,父视图控制器可能不会调用viewWillAppear等。并且知道这样做。在这种情况下,您需要在视图出现时调用子视图控制器,反之亦然。shouldAutomaticallyForwardAppearanceMethodsfalseUINavigationControllerUITabBarControllerbeginAppearanceTransition(_ isAppearing: Bool, animated: Bool)isAppearingtrue

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

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

于 2018-04-23T15:15:33.730 回答
3

根据 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 直到它被调用)为我解决了这个问题。

于 2016-11-24T07:46:59.913 回答
1

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

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

于 2018-03-22T05:51:01.560 回答
1

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

于 2019-11-26T08:50:06.717 回答
0

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

CustomTabBarController -> CustomUINavigationController -> RootViewcontroller

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

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

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

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

于 2019-12-03T05:35:33.643 回答
0

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

在这种情况下,你可以做

addChild(childVC)
childVC.loadViewIfNeeded()
childVC.didMove(toParent: self)
于 2020-12-20T15:15:58.413 回答