I am adding a Child View Controller using this code:
MyCustomViewController * overlayView = [[MyCustomViewController alloc] initWithNibName:@"MyCustom" bundle:nil];
UIViewController *parentViewController = self.tabBarController;
[modalView willMoveToParentViewController:parentViewController];
// set the frame for the overlayView
overlayView.view.frame = parentViewController.view.frame;
[parentViewController.view addSubview: overlayView.view];
[parentViewController.view needsUpdateConstraints];
[parentViewController.view layoutIfNeeded];
// Finish adding the overlayView as a Child View Controller
[parentViewController addChildViewController: overlayView];
[overlayView didMoveToParentViewController:parentViewController];
Then within MyCustomViewController
a button tap triggers a modal view to be presented:
MyModalViewController *vc = [[MyModalViewController alloc] initWithNibName:@"DirectEmployerSignup" bundle:nil];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:vc];
UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStylePlain target:self action:@selector(closeTheModal:)];
vc.navigationItem.leftBarButtonItem = button;
[self.navigationController presentViewController:navigationController animated:YES completion:nil];
Tapping the UIBarButtonItem
triggers closeTheModal:
- (void)closeTheModal:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
After the modal closes, MyCustomViewController
is still visible, but the view stops reacting as expected. The UITextViews
on MyCustomViewController
do not trigger their delegate methods in MyCustomViewController.m
, etc.
For Clarity: I can still tap into the UITextFields
on MyCustomViewController
, and can still see the buttons react when I tap them, but they are not triggering their associated IBActions
, etc.
Any thoughts about what is going on would be very appreciated.
Additional Info
I added a method to close the modal, using [self.navigationController dismissViewControllerAnimated:YES completion:nil];
in MyModalViewController
and pointed the action:@selector()
to the method.
The method in MyModalViewController
fires and closes the modal, but MyCustomViewController
is still not responding.
po [[[[UIApplication sharedApplication] keyWindow] rootViewController] _printHierarchy]
When I run po [[[[UIApplication sharedApplication] keyWindow] rootViewController] _printHierarchy]
, before the Modal view is presented, I see this:
<UINavigationController 0x7fc23985b200>, state: appeared, view: <UILayoutContainerView 0x7fc238f3b760>
| <MyTabBarController 0x7fc23a045400>, state: appeared, view: <UILayoutContainerView 0x7fc238cc7500>
| | <MyNavigationController 0x7fc23985a800>, state: appeared, view: <UILayoutContainerView 0x7fc23b0497e0>
| | | <FirstTabViewController 0x7fc238d47650>, state: appeared, view: <UIView 0x7fc23b1318a0>
| | <UINavigationController 0x7fc23a0bc000>, state: disappeared, view: (view not loaded)
| | | <SecondTabViewController 0x7fc238c8da90>, state: disappeared, view: (view not loaded)
| | <UINavigationController 0x7fc23987c800>, state: disappeared, view: (view not loaded)
| | | <ThirdTabViewController 0x7fc238f77c00>, state: disappeared, view: (view not loaded)
| | <MyCustomViewController 0x7fc238d48e50>, state: appearing, view: <UIView 0x7fc23b086220>
But... After I dismiss the Modal and re-run po [[[[UIApplication sharedApplication] keyWindow] rootViewController] _printHierarchy]
, the <MyCustomViewController 0x7fc238d48e50>
is missing.
Maybe the problem stems from the fact that <MyCustomViewController>
says "appearing" and does not say "appeared" ?
My Solution
I changed MyCustomViewController
from
UIViewController *parentViewController = self.tabBarController;
to
UIViewController *parentViewController = self.tabBarController.navigationController;
Thanks to everyone that helped. I will review your answers with hopes I can accomplish this effect better next time.
The issue is caused by the fact that your MyCustomViewController
got removed from its parent controller. Your events stop being delivered then.
From the code you have posted I cannot say what got the controller removed but you should be able to debug it pretty easily using a breakpoint in -[MyCustomViewController removeFromParentViewController]:
You are either removing it explicitly by mistake or UITabBarController
removes it by itself (could be caused by the issue described below).
However, there is another big issue:
UITabBarController
is a container controller. The whole point of the controller is to manage its child view controllers. That also means that the controller is managing which controller is receiving appearance callbacks (e.g. viewWillAppear:
, viewDidAppear:
and so on). By adding another child view controller you are doing something that is not supported.
For example, when UITabBarController
appears, it sends viewDidAppear:
only to its selected controller. It does not send viewDidAppear:
to your additional controller.
That can lead to many very problematic states and I think this is the root of your problem.
Instead of adding a child controller directly to a UITabBarController
, you can consider the following hierarchy (introducing a common parent for tab bar controller and your custom controller).
UIViewController
| UITabBarController
| MyCustomViewController