dismissModalViewControllerAnimated crashing on iOS6 - iphone

I am facing a crash on iOS 6.0. I have a view controller from which I present a navigation view controller modally and then from the navigation stack I present another view controller modally and finally to dismiss the whole modal stack I pass the following message to my first view controller from where I showed the navigation controller.
Now this works fine on iOS below 6.0. How should I handle this?
[self dismissModalViewControllerAnimated:YES];

I had this similar crash as well and one of the things helped me solve it was adding:
vc.modalPresentationStyle = UIModalPresentationCurrentContext;

maybe because dismissModalViewController is deprecated in iOS6? Try
[self dismissViewControllerAnimated:YES completion:nil];

EDIT: Lets say you add a method to appDelegate called 'makeMeNumberOne:(UIViewController *)vc':
(I know you use the 'modal' versions, they are deprecated in iOS6, switch to 'presented' variants)
. Also I assume you can find the navigationController, if this is a problem add a comment I'll further expand this, and assume you are using ARC.)
the parameter you have is a strong reference, it holds the current presented viewController, lets call it pvc
ask the navigationController for its viewControllers, and get the last one
as a debugging tool, verify that this vc has a non-nil presentedViewController property
message the last view controller above:
[lastOne dismissViewControllerAnimated:NO completion:^{
[navigationController.viewControllers = #[pvc];
}];

Related

Trigger a seque from the AppDelegate to popup a view in the StoryBoard

I am trying to convert my App to a Storyboard, but am having some problems.
In de previous model I could have an 'actionClass' in my AppDelegate which I called when I needed to pop-up a view.
E.g.
DOArticleViewController *articleView = [[DOArticleViewController alloc] initWithArticle:article notification: notification nibName:#"DOArticleViewController" bundle:nil];
[[self navigationController] pushViewController:articleView animated:YES];
But now with the storyboard it does not work anymore.
Then I tried the following code in the AppDelegate:
id currentController = [[[[self window] rootViewController] navigationController] visibleViewController];
[currentController performSegueWithIdentifier:#"settingsSeque" sender:nil];
Don;t think this is the best anyway, as only the rootViewController has all the seques needed, and might not be the visibleViewController, but one step at a time.
With this the only thing I see happening is the message and no action:
Unbalanced calls to begin/end appearance transitions for UINavigationController: 0xb428e00.
I spend a view hours now on trying to figure out to get this to work, but am realising that it might be better to go back to the traditional independent XIB files....
I solved with the answer given in this question: ios: Accessing a navigation controller from app delegate
I tried to get the Navigation Controller, but this was nil and I didn't realise it.
My navigation controller was the rootViewController, so that is also the NavigationController.
Casting the rootViewController to NavigationController and invoking 'visibleViewController' worked fine after that!

setViewControllers of UINavigationController crash app when use with animation:NO

this is working very fine:
[(UINavigationController*)viewController setViewControllers:[NSArray arrayWithObject:cvc] animated:YES];
But This cause my application to crash:
[(UINavigationController*)viewController setViewControllers:[NSArray arrayWithObject:cvc] animated:NO];
the same line I have used in else part with different viewController with animation:NO and it is working fine. Am I missing something or it is a bug?
If you are setting your view controller as rootViewController then do this
yourNavigationController=[[UINavigationController alloc]initWithRootViewController:cvc];
and then when you want to go to newViewController then use pushViewController
[self.navigationController pushViewController:yourViewObject animated:YES];
Apple has given the documentation of this function only with animation set to YES.
- (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);
// If animated is YES, then simulate a push or pop depending on whether the new top view controller was previously in the stack.
I think when you set the animation to 'No' the new top-level NavigationController has not been initialized and loaded properly until the animation is done.

How dismiss a viewController with storyboard from a push segue?

I don't know why dismissViewControllerAnimated:completion:. I just want to do it.
I start with a
[self performSegueWithIdentifier:#"my_segue" sender:self];
But is I call the dismiss than nothing happens. I can create another segue, but it create a new view controller.
My question is: How dismiss the performSegueWithIdentifier:sender:?
Do you have a navigationBar in the viewController that's calling:
[self performSegueWithIdentifier:#"my_segue" sender:self];
If so, you'll need to use:
[self.navigationController popViewControllerAnimated:YES];
to pop the view off the stack. There's one segue call, but the framework seems to call:
presentViewController:animated:completion:
or:
pushViewController:animated:
as appropriate.
Ray
You could just call
[self dismissViewControllerAnimated:YES completion:nil];
from the view controller since the view controller was pushed by segue.
[my_segue_view_controller dismissModalViewControllerAnimated: YES] ?
(not sure, but it works in my practice)
performSegueWithIdentifier:sender: itself isn't dismissed, that's just the method that's called to initiate a named segue. What happens in the segue is of more interest.
You're right that you should call dismissViewControllerAnimated:completion:, and it should be called by the presenting view controller, which has previously called the presented view controller using presentViewController:animated:completion:. For more info, see the UIViewcontroller docs.
Use the below code for Swift 4 version
self.navigationController?.popViewController(animated: true)

Automatically dismiss underling modal view

I'm sharing this as it took me A while to figure out. This is if you need to get rid of a double stack of modal views IF it is pressent.
if(self.parentViewController.parentViewController)
[self.parentViewController.parentViewController dismissModalViewControllerAnimated:YES];
else
[self dismissModalViewControllerAnimated:YES];
I have a view that sometimes gets called from a modal view. In that case I would need to get rid of both views at the same time. While dealing with the situation where it was the only modal view. This worked.
As of xCode 4.2 this is no longer working, The new way to deal with this situation is:
if(self.presentingViewController.presentingViewController)
[self.presentingViewController.presentingViewController dismissModalViewControllerAnimated:YES];
else
[self dismissModalViewControllerAnimated:YES];
As pointed out by #Hollance in a relevant thread of mine:
iOS 5 SDK treating UIViews differently
"There is a new property in iOS 5 named presentingViewController. The meaning of parentViewController got changed a bit with the new container view controller API, so it may not always be set when you think it is. That's what presentingViewController is now for."

iOS Development: What are some reasons that [[self navigationController] viewControllers]; would return nil?

the following statement is returning an nil...
NSArray *viewControllersInNavStack = [[self navigationController] viewControllers];
and this statement is being called in a view controller that's about four levels deep in the navigation stack, so I don't understand how or why it would ever return nil. Your thoughts?
Thanks so much for your wisdom!
Doesn't sound like its your issue, but docs say "Only returns a navigation controller if the view controller is in its stack. This property is nil if a navigation controller cannot be found".
First check if [self navigationController] is returning nil. If not, then viewControllers] must, but break it down first.
what what point are you checking? It may well be that the self.navigationController has not been populated by the environment yet. Can you confirm that self.navigationController isnt nil 0x0?
and if thats the case, you can move your code from init (I'm assuming thats where you have it) to viewDidLoad;
I found the problem. This statement was being called in response to an ApplicationWillResignActive notification. Well, one of the other view controllers higher up the stack was also listening for the same notification and its handler popped that view controller off the stack, along with all the other view controller deeper down the stack, including the one executed the code above. Therefor, by the time the code was executed, its view controller was no longer on the stack.