Ravi Ravi - 5 months ago 12
Objective-C Question

ParentViewController is becoming nil , dont know where and how

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
ContainerViewController
is 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.

Answer

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.