Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

self.navigationController pushViewController not adding controller to stack

I am on a viewController called vcA and I do this:

[self.navigationController pushViewController:vcB animated:YES];

and it works. vcB is pushed. Inside vcB's viewDidAppear I do this:

NSArray *controllers = self.navigationController.viewControllers;

and controllers contains just one object, vcA !!!! (what?)

Why is vcB being added to the controllers array? Is there anything that can prevent that from happening?

thanks.

like image 270
Duck Avatar asked Dec 26 '22 15:12

Duck


1 Answers

I banged my head on the wall for a week to solve this problem involving pushing a view controller on the navigation controller stack.

The problem was this: I was on a navigation controlled based app and I had 3 view controllers, vA, vB and vC.

I was pushing vB from vA using this:

[self.navigationController pushViewController:vB animated:YES];

it worked, but, when I tried to push vC from vB, the self.navigationController property of vB was nil and vB was not on the navigation controller stack. What? Yes, I pushed vB on the navigation stack and vB was not being added to it, but even so, vB was showing correctly.

I discovered that inside vB's viewDidLoad, self.navigationController was not nil and that vB was on the navigation controller stack, but as soon as vB's viewDidLoad ended, vB was removed from the navigation controller stack and its navigationController property was set to nil. At that time, vB was a kind of ghost control, outside the navigation controller stack.

I don't need to mention that from vB I was unable to get back to vA or to push vC.

How that happen?

simple, I was pushing vB from inside a block... something like:

void (^ block1)() = ^(){

   [self.navigationController pushViewController:vB animated:YES];

};

What was happening because a UIKit function (the push thing) was being executed in a block that was probably running on a thread that was not the main thread.

The resolution to that was to wrap the push in a dispatch to the main thread, using this:

void (^ block1)() = ^(){
dispatch_async(dispatch_get_main_queue(),
               ^{
                   [self.navigationController pushViewController:vB animated:YES];
               });

};  

The app had another minor problem with a wrong outlet connected to a viewController, but this was the main problem. This is the kind of problem hard to spot, for being subtle. I discovered the problem when I added another button to the navigation bar and that button did not appear. So, I suspect that something involving UIKit was happening, or not happening in that case. The big problem here is that this code was not crashing, no error message, nothing, just working bad, but working.

like image 125
Duck Avatar answered Jan 21 '23 18:01

Duck