ios 添加为子视图时未调用 UIViewController viewWillAppear

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18235284/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 00:43:29  来源:igfitidea点击:

UIViewController viewWillAppear not called when adding as subView

iosobjective-cuiviewcontrolleruiscrollviewviewwillappear

提问by Fogmeister

I have a UIViewControllerthat I am loading from inside another view controller and then adding its view to a UIScrollView.

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

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

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

I've put breakpoints in the statistics view controller and viewDidLoadis being called but viewWillAppearisn't.

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

Is it because I'm not pushing it onto the hierarchy or something?

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

回答by rdelmar

You should add statisticsControlleras a child view controller of the controller whose view you're adding it to.

您应该将其添加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];

I'm not sure this will make viewDidAppearget called, but you can override didMoveToParentViewController:in the child controller, and that will be called, so you can put any code that you would have put in viewDidAppearin there.

我不确定这是否会viewDidAppear被调用,但是您可以didMoveToParentViewController:在子控制器中覆盖,并且会被调用,因此您可以将您本来要放入的任何代码放入viewDidAppear其中。

回答by AechoLiu

I encounter -viewWillAppear:not called problem again. After googling, I came here. I did some tests, and find out that the calling order of -addSubviewand -addChildViewController:is important.

我又遇到了-viewWillAppear:不叫问题。谷歌搜索后,我来到了这里。我做了一些测试,并找出的调用顺序-addSubview-addChildViewController:是很重要的。

Case 1.will trigger -viewWillAppear:of controller, but Case 2,it WON'Tcall -viewWillAppear:.

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

Case 1:

情况1:

  controller?.willMoveToParentViewController(self)

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

  controller!.didMoveToParentViewController(self)

Case 2:

案例2:

  controller?.willMoveToParentViewController(self)

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

  controller!.didMoveToParentViewController(self)

回答by Alexander Larionov

By default, appearance callbacks are automatically forwarded to children. It's determined with shouldAutomaticallyForwardAppearanceMethodsproperty. Check value of this propery, if it's NOand 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:

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

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

Fixed my problem! Hope it would be helpful.

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

回答by bompf

As mentioned in another answer, the parent view controller might not call viewWillAppearetc. when shouldAutomaticallyForwardAppearanceMethodsis set to false. UINavigationControllerand UITabBarControllerare known to do that. In this case, you need to call beginAppearanceTransition(_ isAppearing: Bool, animated: Bool)on the child view controller with isAppearingset to truewhen the view appears and vice versa.

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

You have to place these calls at appropriate places in your code, normally when you add and remove your child view controller.

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

Don't forget to call endAppearanceTransitionon your child view controller when your custom transition has ended, otherwise viewDidAppearand viewDidDisappearare not called.

不要忘了打电话endAppearanceTransition时,您的自定义转换已经结束,否则你的孩子视图控制器上viewDidAppear,并viewDidDisappear没有叫。

回答by gumbypp

Per Apple (https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html), the correct order of API calls to add a child view controller is:

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

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

But I still had the problem where viewWillAppear in the child VC was not sporadically getting called. My issue was that there was a race condition that could cause the code above to get executed beforeviewDidAppear in the container view controller was called. Ensuring that viewDidAppear had already been called (or deferring the addition of the child VC until it was) solved it for me.

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

回答by Liron

The previous answers are correct, but in case it helps someone - if you override loadViewin the child view controller, then none of the other UIViewController methods get called.

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

Took me some time to realize why my code wasn't running properly, until I realized that I had accidentally overridden loadViewinstead of viewDidLoad.

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

回答by Serg

Check if your parentVC is a UINavigationViewController(or any other container). In this case the shouldAutomaticallyForwardAppearanceMethodsis Falseand the appearance methods are not called.

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

回答by YSR fan

I can't understand your questions and your description. My problem was similar to this only.

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

CustomTabBarController -> CustomUINavigationController -> RootViewcontroller

CustomTabBarController -> CustomUINavigationController -> RootViewcontroller

viewWillAppear of CustomUINavigationController and RootViewController are not getting called unless you switched to another tab and come back.

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

The solution is call super.viewWillAppear(animated: true)

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

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

I struggled for more than a day for this small mistake.

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