可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a UIViewController
that I am loading from inside another view controller and then adding its view to a 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 viewDidLoad
is being called but viewWillAppear
isn't.
Is it because I'm not pushing it onto the hierarchy or something?
回答1:
You should add statisticsController
as a child view controller of the controller whose view you're adding it to.
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 viewDidAppear
get 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 viewDidAppear
in there.
回答2:
I encounter -viewWillAppear:
not called problem again. After googling, I came here. I did some tests, and find out that the calling order of -addSubview
and -addChildViewController:
is important.
Case 1. will trigger -viewWillAppear:
of controller, but Case 2, it WON'T call -viewWillAppear:
.
Case 1:
controller?.willMoveToParentViewController(self)
// Call addSubview first
self.scrollView.addSubview(controller!.view)
self.addChildViewController(controller!)
controller!.didMoveToParentViewController(self)
Case 2:
controller?.willMoveToParentViewController(self)
// Call adChildViewController first
self.addChildViewController(controller!)
self.scrollView.addSubview(controller!.view)
controller!.didMoveToParentViewController(self)
回答3:
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.
回答4:
As mentioned in another answer, the parent view controller might not call viewWillAppear
etc. when shouldAutomaticallyForwardAppearanceMethods
is set to false
. UINavigationController
and UITabBarController
are known to do that. In this case, you need to call beginAppearanceTransition(_ isAppearing: Bool, animated: Bool)
on the child view controller with isAppearing
set to true
when the view appears and vice versa.
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 endAppearanceTransition
on your child view controller when your custom transition has ended, otherwise viewDidAppear
and viewDidDisappear
are not called.
回答5:
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:
[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 before viewDidAppear 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.
回答6:
The previous answers are correct, but in case it helps someone - if you override loadView
in the child view controller, then none of the other UIViewController methods get called.
Took me some time to realize why my code wasn't running properly, until I realized that I had accidentally overridden loadView
instead of viewDidLoad
.
回答7:
In my case, I found that wrongly rewrote a viewWillAppear:
method in my base UINavigationController
class:
override func viewWillAppear(_ animated: Bool) {
super.viewWillDisappear(animated)
// other stuff
}
Note, that instead of calling super.viewWillAppear(animated)
I wrote super.viewWillDisappear(animated)
.
That caused all of UIViewController
's which were inside this UINavigationController
were not calling viewWillAppear:
method.
Hope that helps someone on a similar issue.