present/dismissModalViewController causes UINavigationBar "Back" to lose animation - iphone

I have a UITableViewController that pushes a UIViewController using a UINavigationController:
[self.navigationController pushViewController:detailViewController animated:YES];
In the detailViewController, I present a modal view when the user taps a button (a MFMessageComposeViewController for sending an SMS message) and then dismiss it, like this:
[self presentModalViewController:smsViewController animated:YES];
...
// user pushes Send or Cancel button on the view
...
[self dismissModalViewControllerAnimated:YES];
The SMS modal view dismisses properly, but now when I click the "Back" button on the UINavigationBar, the views don't animate back to the table view. The detail view just disappears and the UITableViewController's view is there. The Back button animates and fades and the selected table cell still has the fading blue effect, but there's no view animation.
Does anyone know why the views don't animate properly? If I don't open the SMS modal view, then the animation works properly, so I'm pretty sure it's caused somehow by the modal behavior.
Here's how my Interface Builder view arrangement looks for this Tab Bar Item:

Please change this line [self.navigationController pushViewController:detailViewController];
to
[self.navigationController pushViewController:detailViewController animated:YES];
And check whether your detailView's viewWillAppear and viewWillDisappear methods set toYES.

I discovered my problem. I am using a custom UITabBarController subclass that overrides -(void)viewWillAppear:(BOOL)animated with some custom tab bar handling. However, I wasn't calling [super viewWillAppear:animated] in the overridden method. Yes, a sad day in my developer life. It still seems odd to me that this would cause the behavior I experienced, but I'm certain it's now fixed due to this change.
Interestingly, the modal push/dismiss animation works properly without the [super viewWillAppear:animated] call in the iPhone 4.3 simulator. But, it does not work in the iPhone 5.0 or 5.1 simulators. (I used a non-MFMessageComposeViewController to text the modal behavior on the iPhone simulator since SMS isn't supported on the simulator).

Related

Subviews are not shown after return from dismiss "mainTabBar" view

I have a UIView (superview) with two sub views (1.UIScrollView and 2.UIView), the first view is a login form, and the second view contains a launch animation (with a UIImageView). When the animation finish, I remove it from superview, then, after the login is validated, it presents a new TabBarViewController, wich has a Home and other navigation controllers. Home navigation controller has a logout button, the action of logout is called method "logout" in tabBarViewController and such method dismisses itself to back login form.
#implementation LoginViewController
MainTabBarViewController *mainTabBarViewController = [[self storyboard] instantiateViewControllerWithIdentifier:#"MainTabBarViewController"];
[self presentViewController: mainTabBarViewController animated: YES completition: nil];
Logout works fine as long as the keyboard is never shown, otherwise the login form doesn´t appear, the superview does.
#implementation MainTabBarViewController
-(void)logout{
[self dismissViewControllerAnimated: YES completition: nil];
}
I notice that loginView (1.ScrollView) is in the top of the stack and hidden property is NO.
Any ideas? Thank you in advance
NOTE: I use ARC, storyboard and iOS 5
I found the problem, in my loginView I adjust the frame in UIScrollView to move to visible area the TextField when keyboard appears, I did this registering keyboard notifications, so, when the keyboard appeared somewhere, the loginView fall into one invisible area, so the solution was register keyboard notificacion when loginView appear and unregister when disappear.
Thank you, and sorry about my english!!

black bar as the view fades when I am using navigation controller

I'm writing my first iPhone app and I am trying to figure out how to have a MasterView and DetailsView like in the example. However, instead of using a TableView, I want to use a button on the MasterView to go to the SignUpView. I want the MasterView to NOT have a navigation bar but the SignUpView needs to have one.
I have tried putting a NavigationController into the MasterView using the interface builder. This doesn't seem to do anything at all ... I.e. I make the following call:
[self.navigationController pushViewController:signUpViewController animated:YES];
And nothing happens. The SignUpView is never shown.
So then I declared a NavigationController in the AppDelegate. The above call in the same function that it was in before (button handler, button is in MasterView) works now! It takes me to the SignUpViewController.
however, the issue is, when I press back on the navigation bar in the sign up view, the navigation bar shows up again in the MasterView. I tried to set
self.navigationController.navigationBarHidden = YES;
in viewDidLoad and viewDidAppear, but that causes a black bar to appear in the transition from SignUpView to MasterView.
I tried to not set it in one of the two, and that causes the animation to go smoothly, but the navigation bar shows up in the MasterView.
I feel like this should be pretty simple to do ... but I'm at my wits end trying to figure this out. Some help would be really appreciated!
Thanks.
Probably not the answer to your question, but just a small suggestion. In the many apps that I have come across, a sign-up/sign-in view is generally displayed as a modal view (on top of your master view) with a 'cross' in the top-right corner to dismiss it. Probably it results in a better user experience.
Also, did you try self.navigationController.navigationBarHidden = YES; in the MasterView's viewWillAppear ?
HTH,
Akshay
I had this problem too, until I discovered setNavigationBarHidden. You will probably want to use these in viewWillAppear/viewWillDisappear or viewDidAppear/viewDidDisappear. You don't want to call this in viewDidLoad because that is only called once when the view is initialized, not every time it appears.
To hide:
[self.navigationController setNavigationBarHidden:YES animated:YES];
To show:
[self.navigationController setNavigationBarHidden:NO animated:YES];

UINavigationController not popping UINavigationBar items on iPad

I'm having a very strange problem with the UINavigationController.
I found a very similar question here:
UINavigationController not popping UINavigationBar items
but the solution there had to do with the fact that the guy had added a category to NSMutableArray, and I'm not doing anything like that.
In short, the problem is this: I have a navigation controller and I'm pushing a few view controllers on it. Then when the 'back' button is tapped the view controller is popped, but the corresponding navigation item isn't. If I tap back again, then the navigation item is popped.
Besides, it only happens when using the back button from the navigation controller's navigation bar. If I call popViewController explicitly (for example from a button press), it works as expected.
And this only happens on my iPad running OS 3.2, but not on my iPod Touch running OS 3.0 or on the simulator.
I've been trying to isolate the problem in a separate project from the rest of my app so I can experiment with it, but I can't get it to reproduce, though it occurs 100% of the times on specific views in my app.
I know that's not nearly enough information to get an specific answer, but I just wanted to know if anyone ever heard of a navigation controller not popping the navigation items as expected, just so I could have some clue as to where to investigate next.
Here's an example of the code I use to push a view controller, it's pretty straightforward, I'm not trying to do anything special with it:
// pushing a view controller from a button press (set up with interface builder)
- (IBAction) tappedExtras
{
ExtrasViewController *controller = [[ExtrasViewController alloc] initWithNibName:#"ExtrasViewController" bundle:nil];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
}
note: in that example I'm using a custom view controller class called ExtrasViewController, but the problem happened with any kind of view controller I tried.
And here's a bit of code used to pop the view controller explicitly, also triggered by a button press set up with interface builder:
- (IBAction) cancelChanges
{
userCancelled = YES;
[self.navigationController popViewControllerAnimated:YES];
}
this works perfectly (popping the view controller explicitly), but on the exact same view controller if instead of tapping the button set up with interface builder you tap the back button on the navigation bar, the navigation item is not popped correctly.
I got the same issue with navigation that subsist after poping the third level pushed view controller.
The issue only appear in landscape on iPad. No issue on the iPhone (3.1.3 & 4.0). Of course, it's ok on the simulator.

Presenting ViewController behind another one

I have image picker which collects data for another view controller (TTMessageController from three20) and I want this message composer to appear behind image picker, so when image piker slides out there will be already appeared message controller with pre-filled data.
Code like this
[self.navigationController presentModalViewController:composeController animated:NO];
[picker dismissModalViewControllerAnimated:YES];
and vice-versa wont work at all. What to do? How to present composeController behind already presented picker controller?
Thanks in advance.
Actually removing animation from both viewController help.
[picker dismissModalViewControllerAnimated:NO];
[self presentModalViewController:composeNavController animated:NO]; // If YES it crashes
But it's not to iPhone-ish if get what I mean, even fade throw black or just some visual effect will make it look much, much nicer. Technically tho, it works.
Edit:
Ok I think the problem here is the modal bit, as the iPhone really appears to not like you having 2 views set to modal, or even animating from one modal view to another.
Do they definitely have to be modal? How about adding them to the normal navigation stack?
You could add the message view to the stack first (non-animated) so that it's there when you pop back one.
Try this:
The order in which you add views to the stack affects the order that they will display in when you dismiss them.
This part adds the composeController to the stack and then animates the picker going on top. Use this code to display the picker controller (ie instead of modal dialog):
[self.navigationController pushViewController:composeController animated:NO];
[self.navigationController pushViewController:picker animated:YES];
Then, when you are done with the picker, you can "pop" the view back to the message composer:
[self.navigationController popViewControllerAnimated:YES];
You should now have no references to any modal dialogs remaining in your code. I believe this should work much better than modal, which really is for displaying one view above every other one, not for switching from view to view.
Hope that helps!
Instead of trying to present another viewController behind the picker, you could dismiss the image picker modal view controller, push the Message controller (both with animated:NO), and then use a CATransition to perform your own Cocoa-like animation of the image picker animating off screen.
You need to split these animations up so they don't execute in the same runloop. I've run into a situation where the OS does not like dismissing and presenting modal views back to back.
Try this:
- (void)myCallbackMethod{
[picker dismissModalViewControllerAnimated:YES];
[self performSelector:#selector(presentMessage) withObject:nil afterDelay:0.25];
}
- (void)presentMessage{
[self.navigationController presentModalViewController:composeController animated:YES];
}

Hiding just one navigationBar in navigationController stack

I am trying to get the same functionality as contacts app in iphone. The problem is following , when i hide navigationbar using following command
[self.navigationController setNavigationBarHidden:YES animated:YES]
It gets hidden throughout all viewControllers in navigationController stack.
I am implementing search in my application pretty much the same way it is in Contacts app. When user touches search field it hides navigationBar, but when user selects item from table view transition I want it to stay hidden in rootViewController and to be visible in pushed viewController.
I was thinking about completely hiding navigationControllers navigationBar and placing my own navigationBar, but i am not sure is it right direction to take.
add following code tot the desired view controller, and it will work fine
- (void) viewWillAppear:(BOOL)animated{
[[self navigationController] setNavigationBarHidden:NO animated:YES];
}
hope it helps.