Question

I am trying to make an app and the first step is to create viewControllers and link them . I know i can do that using storyboards and sueges but i wanted to do it the old school way - by coding i.e.

It contains 4 view controllers

-MainViewController
-SettingsViewController 
-RulesViewController

The three view controllers are managed using ContainerViewController(4th viewController) (custom container which i wrote) . The currentSubViewController keeps track of the viewController currently being shown

@implementation ContainerViewController
{
     UIViewController * currentSubViewController;
}

All three viewControllers are created from .nib

  • Main Page has 2 buttons "Settings" and "Rules"
  • Settings has 2 buttons "Main" and "Rules"
  • Rules has 2 buttons "Main" and "Settings"

On start up :

currentSubViewController is set to an instance of MainViewController and then

[container addChildViewController: currentSubViewController]

makes container the parent of currentSubViewController.

And the main page shows up without any problems

After start up on pressing the "settings button"

IBAction in MainViweController is called

- (IBAction)onSettings:(id)sender {
        if ([self parentViewController]) {
             [(ContainerViewController*)[self parentViewController showViewControllerWithName:@"settings"];
}
}

And then showViewControllerWithName of ContainerViewControlleris called

- (void) showViewControllerWithName:(NSString*)vctype
{
    UIViewController * toVC = [ViewControllerFactory getViewControllerOfType:vctype]; // viewController factory returns the appropriate viewController i.e either MainViewController or SettingsViewController or  RulesViewController

    toVC.view.frame = containerView.bounds;
    toVC.view.autoresizingMask = containerView.autoresizingMask;

    [currentSubViewController willMoveToParentViewController:nil];

    [self addChildViewController:toVC];

    [self transitionFromViewController:currentSubViewController
                  toViewController:toVC duration:1.0 options:UIViewAnimationOptionCurveLinear animations:^{} completion:^(BOOL finished){
                      [currentSubViewController removeFromParentViewController];
                      [toVC didMoveToParentViewController:self];

                  }];
    currentSubViewController = toVC;

// I checked here toVC has a parentViewController set to ContainerViewController
}

SettingsViewController shows up

On Pressing the "Main" Button on SettingsViewController

IBACtion in SettingsMainController is called

 - (IBAction)onMain:(id)sender {
    if ([self parentViewController]) { // parentViewController is nil here
        [(ContainerViewController*)[self parentViewController] showViewControllerWithName:@"root"];

    }
 }

But ParentViewController is nil here and hence nothing is shown. The SettingsViewController is toVC from the function call showViewControllerWithName in the previous step.

Somewhere between showViewControllerWithName() and OnMain(), parentViewController is being set to nil. I checked till viewDidAppear and parentViewController is not nil until that point.

My Questions are

  1. Where is parentViewController being set to nil?
  2. To debug this issue i would want to know what other internal functions are called after viewDidAppear
  3. Is using a factory class to create new UIViewControllers creating a problem?
  4. is instance being created and instance being shown different?although I checked the memory address in the debugger its the same

I am unable to fix this. I tried a very hacky way where i keep track of the parent in the derived class even then transitionFromViewController: throws an exception saying both view controllers should have same parent.

I am stuck at this for almost two days now. I Would really appreciate some help.

Was it helpful?

Solution

Well I finally was able to make it work . Let me concisely explain the question again

->ContainerViewController presents MainViewController and when you check MainViewController.ParentController, it is infact ContainerViewController

->ContainerViewController transitions from MainViewController to SettingsViewController using the following function

  (void) showViewControllerWithName:(NSString*)vctype
  {
     UIViewController * toVC = [ViewControllerFactory getViewControllerOfType:vctype]; 
    toVC.view.frame = containerView.bounds;
    toVC.view.autoresizingMask = containerView.autoresizingMask;

    [currentSubViewController willMoveToParentViewController:nil];

    [self addChildViewController:toVC];

    [self transitionFromViewController:currentSubViewController
              toViewController:toVC duration:1.0 options:UIViewAnimationOptionCurveLinear animations:^{} completion:^(BOOL finished){
                  [currentSubViewController removeFromParentViewController];
                  [toVC didMoveToParentViewController:self];

              }];
    currentSubViewController = toVC;


}

->After the transition SettingsViewController.parentViewController is nil

Following is the fix :

           animations:^{} completion:^(BOOL finished){
                  [currentSubViewController removeFromParentViewController];
                  [toVC didMoveToParentViewController:self];

              }];

    currentSubViewController = toVC;

is changed to

           animations:^{} completion:^(BOOL finished){

              }];
    [currentSubViewController removeFromParentViewController];
    [toVC didMoveToParentViewController:self];
    currentSubViewController = toVC;

And now SettingsViewController has a parent.

Well, If anyone could explain what exactly is going on then it would be great.

OTHER TIPS

I just wanted to ring in here. I had a parent/child layout setup with storyboard which was working great until one day....

It turned out I wrote a utility method named: -(UIViewController*)addChildViewController:(UIViewController*)chidViewController

It turns out I wasn't very creative with my method name and I overwrote a UIViewController method. All I had to do was rename it and I was back in business. This took me a long time to track down!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top