there have 3 view controllers, A,B,C, all designed in storyboard.
in all pushViewController: controllers were got from [self.navigationController instantiateViewControllerWithIdentifier:#"A/B/C_Controller"];
In A_ViewController ( root controller ):
-(void)viewWillAppear
{
[self.navigationController pushViewController:B_Controller animated:YES];
}
In B_ViewController:
-(IBAction)someButtonClick
{
[self.navigationController pushViewController:C_Controller animated:YES];
}
In C_ViewController:
-(IBAction)someButtonClick
{
[self.navigationController popToRootViewControllerAnimated:YES];
}
Problem:
A_viewController -> B_viewController -> C_viewController is fine.
but after popToRootViewController to A From C, A can't push to B anymore.
and other pushViewController: all can't works, popViewControllerAnimated: also cause crash.
Note.
have tried
// in A view
dispatch_async(dispatch_get_main_queue(),^{
[self.navigationController pushViewController:B_viewController animated:YES];
})
in this post, but it doesn't works for me.
does anyone know what happens in view controller stacks?
have struggling in this issue all day, any help will be appreciated!
When you When you popToViewController from C, the viewWillAppear method will in A be called just before the animation. Now, at this point, since the transition is in progress, you might get some kind of warning in the debugger like:
"Warning: Attempting to push .... while a transition is in progress"
You need to call the navigation controller methods in such a way that they do not overlap each other.
Calling pushViewController in the viewDidAppear method of A would be better in this context.
Related
I have inherited my ViewController from BaseViewController and I have pushed my SecondViewController using storyboard ID.but, when I am trying to popview from second view to view controller its not working.
Here is my code:
dispatch_async(dispatch_get_main_queue(), ^{
[self showMesssgeonAlert:#"Success"];
[self hideProgress];
[self.navigationController popViewControllerAnimated:TRUE];
});
Even i tried with :
NSArray *controllerArray = self.navigationController.viewControllers;
for (id controller in controllerArray)
{
if ([controller isKindOfClass:[ViewController class]])
{
[self.navigationController popViewControllerAnimated:TRUE];
}
}
but,its not working in both the conditions.What should I do?Please help me.
Make sure you are pushing the controller SecondViewController on ViewController, If you are using segue then check the show type like (Push, Present Modally). If this is correct then check the navigation controller object, it should have an object.
Finally check the memory address of navigation controller in both the view controllers did load method. It should same.
You should double check:
Both the view controllers should be on same navigation controller stack.
I guess, second view controller is on different navigation controller.
How you're pushing to second view controller?
Try using appDelegates navigation controller so, try as follow:
dispatch_async(dispatch_get_main_queue(), ^{
[self showMesssgeonAlert:#"Success"];
[self hideProgress];
[((AppDelegate*)[[UIApplication sharedApplication]delegate]).navigationController popViewControllerAnimated:TRUE];
});
Split view controller may cause this issue, in my case, I removed it, and popViewController started working.
I want to pop the last view in my app, so I'm calling this function:
[self.navigationController popViewControllerAnimated:YES];
and self is the last view controller, I expect that the app will exit, but that does't happen why ?
For going to the rootView u need to call as below,
[self.navigationController popToRootViewControllerAnimated:YES]; // Returns the root/last vie controller.
and the one u used is below,
[self.navigationController popViewControllerAnimated:YES]; // Returns the popped controller.
If you wish to exit your app, just do that:
[[NSThread mainThread] exit]
Anyway, your way:
[self.navigationController popViewControllerAnimated:YES];
It's common in android, not in iOS.
Im trying to dismiss a ModaViewController called C, back to A. The ModalViewController is presented in B. Therefore the Navigation flow is A->B - (present ModalView) -> C. I am able to dismiss the ModalViewController back to B, but I am unable to pop back to A in the completion bracket. This is the code I have tried:
[self dismissViewControllerAnimated:YES completion:^{
[self.navigationController popToViewController:[[self.navigationController viewControllers] objectAtIndex:0] animated:YES];
}];
The ModalViewController is dismissed but does not pop back to A. I call this block of code in an IBAction.
Any advice?
On a second note, when I dismiss the ModalViewController all my UIPickers in Controller B are empty/ deallocated. I am using ARC as well.
The problem with your code is that self.navigationController will be nil. If you have a controller (A) embedded in a navigation controller, and that controller pushes to another controller (B) which then presents your last controller (C), then you need to do something like this,
-(IBAction)dismissToBThenPop:(id)sender {
UINavigationController *nav = (UINavigationController *)self.presentingViewController;
[self dismissViewControllerAnimated:YES completion:^{
[nav popViewControllerAnimated:YES];
}];
}
Even though you present C from B, the actual presentingViewController will be the navigation controller. This code will dismiss C then pop B, but you will see B for an instant before ut pops back to A. If you don't want to see this, then you should use an unwind segue to go directly back to A from C.
Your second problem about the pickers being empty and deallocated should not be happening under the scenario that you say you have. You will have to provide more information about what you're doing in B to solve that problem.
Create a protocol in ModalViewController, let's say ModalViewControllerDelegate with a method -(void)dismissTheModal, and make B implement this protocol. Before showing the ModalViewController, do modalViewController.delegate = self. When you're IBAction is called, do [self.delegate dismissTheModal], and in controller B you should do :
-(void)dismissTheModal {
[self dismissViewControllerAnimated:YES completion:^{
[self popViewController];
}];
I have UITableViewController called EditPoint in a UINavigationController that are presented in a UIPopoverController.
Sometimes EditPoint is the root UITableview, sometimes another UITableviewContoller pushes EditPoint.
Is there a way that I can tell in EditPoint TableViewController to tell if another one pushed it into view or if its the root?
I push EditPoint:
[self.navigationController pushViewController:tableView animated:TRUE];
then in EditPoint I tried:
DLog(#"self.navigationController.presentingViewController: %#", self.navigationController.presentingViewController);
DLog(#"self.navigationController.presentedViewController: %#", self.navigationController.presentedViewController);
DLog(#"self.presentingViewController: %#", self.presentingViewController);
DLog(#"self.presentedViewController: %#", self.presentedViewController);
and they all return NULL.
But if I try:
[self.navigationController popToRootViewControllerAnimated:TRUE];
or any of the other pop methods, it works.
Any idea why I can't figure out what the presentingViewController is?
The end result is I need to tell if there is a back button or if I need to put a button there that says Cancel. Is there a better way to figure this out?
Use self.navigationController.viewControllers to check if self is the root view controller at its nav controller stack, the properties you are using should be used when the controller is presented as modal.
I work on a legacy application, and have found out, that my view[Will/Did]Disappear methods are not always fired properly.
The case is, I have a (custom) UIViewController set as rootViewController in AppDelegate. This rootViewController has a UINavigationController, which has two view controllers pushed on it. When the user presses the home button, the user is logged out. When he later returns to the app, the application calls [UINavigationController popToRootViewControllerAnimated:YES] and then displays a modal UIViewController for logging in.
The problem is: When I push/pop on the UINavigationController normally, my viewWillDisappear method is called properly. But when I use the popToRootViewControllerAnimated: method, viewWillDisappear is not called on any of the viewControllers that are popped off.
Searching on the internet has only given two possible reasons:
If using a UINavigationController as a subview, you must call view[Will/Did]Disappear yourself
Not calling the proper super methods
None of these suggestions are the case in my app. And I have no idea where to look. Anybody has a suggestion to what has been done wrong in the app?
The view probably wasn't onscreen. It has to be onscreen (visible) for the viewWillDisappear: method to be called. If it's coming back from the background, it wasn't visible.
You could try using willMoveToParentViewController: which is called when the view controller is removed from its parent.
such useful to me
[nav performSelector:#selector(popToRootViewControllerAnimated:) withObject:nil afterDelay:0.0];
I rewrote UITabBarController
- (void)setSelectedIndex:(NSUInteger)selectedIndex {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
UINavigationController *navigationController = [originalViewController as:[UINavigationController class]];
if (navigationController.presentedViewController) {
[navigationController dismissViewControllerAnimated:NO completion:^{
[navigationController popToRootViewControllerAnimated:NO];
}];
}else if (navigationController.topViewController){
[navigationController popToRootViewControllerAnimated:NO];
}
});
}