dismissing UINavigationController in iOS 5 - objective-c

My problem seems to be a bit weird, I have a custom UITarBar which manages several UINavigationControllers with a UIViewController that presents those NavControllers modally on a UITabBar button touchUpInside, so in iOS 5 my app is crashing because of the dismissModalViewControllerAnimated: method ... And if change the dismiss method to the new one on iOS 5 (dismissViewControllerAnimated:completion:) it does not dismiss the NavController. Here is some code on how I'm changing controllers:
- (void) changeController
{
if ([self.generalViewController respondsToSelector:#selector(dismissViewControllerAnimated:completion:)]) {
[self.generalViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
} else {
[self.generalViewController dismissModalViewControllerAnimated:NO];
}
[self.anotherNavController.view addSubview:customTabBar];
if ([self.generalViewController respondsToSelector:#selector(presentViewController:animated:completion:)]) {
[self.generalViewController presentViewController:anotherNavController animated:NO completion:nil];
} else {
[self.generalViewController presentModalViewController:anotherNavController animated:NO];
}
Everything is managed in the AppDelegate. Thanks in advice.
EDIT: I found something on this post dismissModalViewControllerAnimated: (and dismissViewControllerAnimated) crashing in iOS 5 and did what he did (presented the first viewControllerAnimated animated) and then everything like I had before the iOS 5 checks for new presentViewController's selectors and everything works fine on simulator but not on device ..

I am unsure about your first lines, and think the first lines should perhaps be:
if ([self.generalViewController respondsToSelector:#selector(dismissViewControllerAnimated:completion:)]) {
[self.generalViewController dismissViewControllerAnimated:YES completion:nil];
You have an extraneous .presentingViewController in the second line of the above presently. I see in your comment above you have a rationale for it, but have you tried the alternative?
Regardless, I had a related problem with the move to iOS 5, and found that the solution was to simply send the dismiss commands thusly:
[self dismissViewControllerAnimated:YES];
I suggest you try it. It worked for me, and also still worked in iOS 4.2 as well when I ran the code there...
Edit: Correction, it was dismissModalViewControllerAnimated that I was correcting. However, in that case I found that just sending the message to self rather than targeting a view controller was what fixed the problem of not being able to dismiss the view, and worked in both iOS 4 and 5... Couldn't hurt to just try.

Related

navigationController popToRootViewControllerAnimated not working in iOS 8

I have a login UIViewController embedded in a UINavigationController that a user enters UserID/Password then clicks [Login] button looks like this:
2-textfields and a UIButton, when the user clicks the button I run the code:
-(void)btLoginTapped:(id)sender{
[doLogin];
NSLog(#"Login Successful.")
[self.navigationController popToRootViewControllerAnimated:YES];
}
now my problem arises when I use Simulator or a Device with iOS 8
I will see the Log-message but the ViewController will not pop where as when I use a Simulator/Device with iOS 7 the view will pop to root as normal.
why won't
[self.navigationController popToRootViewControllerAnimated:YES]
work in iOS 8+ but it'll work in iOS 7+?
Mind you I have changed the Animated flag to NO, I also tried:
[self.navigationController popViewControllerAnimated:YES/NO] but still same issue?!!
Any Input is appreciated. Thank you.
Try this
[self dismissViewControllerAnimated:YES completion:nil];
instead of popToRootViewControllerAnimated if you can push your root view controller then it will work.
Hope it helps.

Application tried to present modally an active controller : UIImagePickerController

I'm struggle at this for 2 days and believe that this is the moment I should call for help. After I search SOF for a while, none of any answer could solve my problem. Here are my application ...
In the application,
Device is iPad, iOS 6
RootViewController is NavigationController
TopViewController is TabBarController
In this TabBarController, I present a popoverController from right bar button of navigation bar
In presenting popover there is a button to allow user to pick image from by taking new one or pick from existing.
To pick new one, I presentViewController UIImagePickerController to allow user to take photo with divice camera. presentModalViewController:animated: if iOS < 6, and presentViewController:animated:completion: for iOS > 6
I also hide Status Bar before presentation
To select from existing photo, I do presentPopoverFromBarButtonItem:permitArrowDirections:animated:
PopoverViewController also referencing by A TabBarController
Here is the issue
Present UIImagePickerController will always failed if user try to pick new one first with exception "Application tried to present modally an active controller <[name of view controller that try to present]>"
BUT, if user try to pick image from camera roll for once and then try to take new one again, it won't fail.
Here are what I tried
present from RootViewController
present from TopViewController (TabBarController)
present from popoverViewController itself
present from a tab of TabBarController
hide popoverViewController before presentation
resignFirstResponder from a textField in popoverViewController
Here is the current code I'm using
// PopoverViewController, presented by a tab in TabBarController
- (IBAction)takePhoto:(id)sender {
[self.delegate takePhotoWithDeviceCamera];
}
// A Tab in TabBarController, delegate of popoverViewController
- (void)takePhotoWithCamera {
[[UIApplication sharedApplication] setStatusBarHidden:YES];
if ([UIDevice OSVersion] < 6.0) {
[self presentModalViewController:cameraPicker animated:YES];
} else {
[self presentViewController:cameraPicker animated:YES completion:nil];
}
}
Any idea what would cause this error? Any suggestion are welcome. Thank you.
Got the same trouble than you and finally got the solution based on #CainaSouza's answer. I've been working with Xamarin.iOS so I'll make my answer in C#, but it can be easily translated to Objective-C.
I'm using the same code as #CainaSouza to call the controller:
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController (customController, true, null);
And then I add the following code to my custom RootViewController:
public override void PresentViewController (UIViewController viewControllerToPresent, bool animated, Action completionHandler)
{
if (PresentedViewController != viewControllerToPresent) {
base.PresentViewController (viewControllerToPresent, animated, completionHandler);
}
}
The trick is to check if you haven't presented that UIViewController before.
I know it's an old question, but hope it will help someone. :)
Present the imagePicker controller in a popoverController(in case of iPad). This will not give you that error.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:picker];
[popover presentPopoverFromRect:self.selectedImageView.bounds inView:self.selectedImageView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
self.popOver = popover;
}
else {
[self presentModalViewController:picker animated:YES];
}
Best Regards.
Have you tried to present it like this?
[self.view.window.rootViewController presentModalViewController:cameraPicker animated:YES];
My guess is that the cameraPicker instance is not correctly allocated/released. Try creating the cameraPicker inside your - (void)takePhotoWithCamera method rather than relying on a previously created instance. You'll get a handle to the picker instance in the callback methods...
I had the same problem - I wanted users to take photos using a full screen view (i.e. call presentViewController and pass UIImagePickerController controller instance) and select existing photos from a popover (I associated it with a popover using initWithContentViewController). I reused the same instance of UIImagePickerController for both camera and popover and it threw the same exception if I tried to run a camera before opening a popover.
I turned out to cause a problem and my solution was simply to have two instances of UIImagePickerController - one for camera (which I presented from a main view) and another one for popover. It works so far. :-)
Not sure if it is still actual for the original poster, but hopefully it will help anyone else who encounter this discussion.

setStatusBarOrientation:animated: not working in iOS 6

I've used this code to force an orientation change back to portrait when the user is finished watching the video (it allows viewing in landscape mode), before popping the video view controller off the navigation controller:
//set statusbar to the desired rotation position
[[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationPortrait animated:NO];
//present/dismiss viewcontroller in order to activate rotating.
UIViewController *mVC = [[[UIViewController alloc] init] autorelease];
[self presentModalViewController:mVC animated:NO];
[self dismissModalViewControllerAnimated:NO];
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
This worked perfectly until iOS 5.1.1. I've even tried to use the new present/dismiss methods after reading in another post that those should be used now:
[self presentViewController:mVC animated:NO completion:NULL];
[self dismissViewControllerAnimated:NO completion:NULL];
The problem is it doesn't work at all. After I rotated the video viewer to landscape and then pop it, my settings view (table view controller) comes back, but also in landscape mode.
I've even tried the tip from Here
"The setStatusBarOrientation:animated: method is not deprecated outright. However it now works only if the supportedInterfaceOrientations method of the topmost full screen view controller returns 0. This puts the responsibility of ensuring that the status bar orientation is consistent into the hands of the caller."
So I've experimented with setting a flag to force supportedInterfaceOrientations to return 0 (before calling the first code block above) but it doesn't work either.
Does anybody have a solution for this?
Thanks for your time and effort.
setStatusBarOrientation method has changed behaviour a bit. According to Apple documentation:
The setStatusBarOrientation:animated: method is not deprecated
outright. It now works only if the supportedInterfaceOrientations
method of the top-most full-screen view controller returns 0
Your root view controller should answer false to the method shouldAutorotate in order that your app responds to setStatusBarOrientation:animated
From Apple Documentation: "if your application has rotatable window content, however, you should not arbitrarily set status-bar orientation using this method"
To understand that, put a breakpoint in the shouldAutorotate method and you will see that it is called juste after setting the status bar orientation.
Here is how I fixed.
https://stackoverflow.com/a/14530123/1901733
The current question is linked with the question from the url above.
The statusBarOrientation is a real problem in ios6.

upgraded to xcode 4.2 now exc_bad_access on dimissModalViewcontroller

Hi I'm having a weird problem.
My app is based on the samplecode of "PageControl" (the Apple example).
It uses a horizontal scrollview in which most of the stuff is happening.
At he bottom I have a UIToolbar from which I call a modal viewcontroller.
On XCode 4 everything worked like a charm, after the upgrade to XCode 4.2 (with the new SDK) I get a "exc_bad_access" on dimissModalViewcontroller.
The funniest thing is that it does not happen rightaway but only after 2 or 3 times presenting and dismissing the modalViewcontroller.
To simplify things I went back to the original samplecode and tried to implement the modalVieWcontroler in that context. No luck so far.
In the original PageControl Code I changed the type of "ContentController" from NSObject to UIViewController like so:
#interface ContentController : UIViewController
{
NSArray *contentList;
}
I call presentModalViewcontroller in a sub class (from ContentController) named PhoneContentController like so:(I use a notification so I can call it from anywhere)
-(void) showExplanationsModal:(NSNotification*)notification{
ExplanationsViewController *xplViewController = [[[ExplanationsViewController alloc] initWithNibName:#"Explanations" bundle:nil]autorelease];
[self presentModalViewController:xplViewController animated:YES];
}
The dismissal of the modalViewcontroller is called from the modal view itself like so:
(the notification is used tot initiate some other stuff)
- (IBAction)onClose
{
[self dismissModalViewControllerAnimated:YES];
[[NSNotificationCenter defaultCenter]postNotificationName:#"dismissExplanationsModal" object:self];
}
This code works fine with iOS4 SDK but renders occasional excec_bad_access with iOS5 SDK.
When I compile the app with iOS4 SDK it also rus fine on iOS5 devices.
I tried using Zombies but this does not point to a specific over-released object.
I'm sort of stuck on this one for a few days already ...
I have put up a copy of a sample project that illustrates the problem here http://www.sesni.biz/pagecontrol.zip
It seems for me that problem is in the onClose method. Try first sending the message, without the object (this object will be invalidated soon).
- (IBAction)onClose
{
[[NSNotificationCenter defaultCenter]postNotificationName:#"dismissExplanationsModal" object:nil];
[self dismissModalViewControllerAnimated:YES];
}
Found the problem: I changed the type of ContententController from NSObject to UIViewcontroller. This worked fine with the iOS4 SDK but crashes with iOS5 SDK.

Closing a view displayed via a modal segue

I'm manually invoking a segue (set as modal) in order to display a login form in Xcode 4.2 using Storyboards with the following line of code:
[self performSegueWithIdentifier:#"LoginSegue" sender:nil];
I'm probably missing something really simple, however I can't find a way to programmatically close the login view and return to the previous view.
The view is part of a navigation view controller, so setting the segue type to "push" allows me to use the back button to send me back to my previous screen, but in "modal" mode, I'm not entirely sure how to achieve this (after button press, for example)
Any help would be much appreciated.
If your deployment target is iOS 5.0 or later, use this message:
[self dismissViewControllerAnimated:YES completion:nil];
Or in Swift:
self.dismissViewControllerAnimated(true, completion: nil)
If your deployment target is older, use this (deprecated) message:
[self dismissModalViewControllerAnimated:YES];
[self dismissViewControllerAnimated:YES completion:nil]; is a new way in IOS5
The following should work fine...
[self dismissModalViewControllerAnimated:YES];
I do exactly this with a login page in my latest tutorial here, with no issues.
The following code works in swift 3:
self.dismiss(animated: true, completion: nil)