I'm doing a storyboard segue when tapping a navigation bar button item, from view controller A to view controller B, and it works fine with a push animation. But when I tap the back button (no custom code) the previous view (A) just pops into place without the sliding animation. The same happens when I do a [self.navigationController popViewControllerAnimated:YES], i.e. there's no animation. I've made sure that I'm only popping it once.
This has been tested in the simulator as well as on a device.
I suspect it has something to do with what happens when view controller B is being unloaded or something similar, but I can't put my finger on it. I am handling an ABRecordRef property in B, but I have tried to be careful to call CFRetain and CFRelease in the setter when appropriate. I'm doing calls to outlets in various setters and getters but again have been careful to only do it if the view is loaded in case that would cause the view to reload after being unloaded. No success.
Finally did a log in B's viewWillDisappear, and animated is set to false. Why's that?
I don't know what to do next, my segue has the "push" style in the storyboard.
Related
I have a UINavigationController subclass, which manages a custom navigation bar. This navigation bar's look depends on the top view controller. I ask the top view controller about the type of the bar to be displayed when -pushViewController:animated: or -popViewControllerAnimated: happens.
The problem is, that the navigation bar type change is played when the user starts swiping but I could not find any event which tells me that the swipe was successful or not, so if the user cancels the swipe, I stuck on the previous view controller with the desired navigation bar look of the one below it in the navigation stack.
I have tried UINavigationControllerDelegate, but neither -navigationController:didShowViewController:animated: nor -navigationController:didShowViewController:animated: gets called. My second thought was to use interactiveGestureRecognizer, but it seems it it ends successfully both on successful and cancelled back swipe, and the topViewController is also still the same when the recognizer event is called.
I know, that the top view controller's -viewDidAppear will be called again upon cancelled swipe, but I don't want my users to implement any logic in their controllers to support my navigation implementation.
Any ideas?
Try using the UINavigationControllerDelegate, you can rely on its callbacks to know when a viewController is going to be displayed or not.
Getting interactivePopGestureRecognizer dismiss callback/event
I have scene from where I call a another modal scene.
Once modal scene completes or on click of ok button on modal scene, I call an unwind segue to return back to main scene. My unwind segue method is defined in the first scene.
In unwind segue method I call another push scene but I get following warning in "nested pop animation can result in corrupted navigation bar" which ultimately crash my application
That error is definitely triggered by send pop view controllers messages more than once at the time. I suggest you to check your code, maybe you are not aware that something are trigger this action. It's difficult to say without seeing your code.
In my case I was popping the view controller after a nsnotification came but I forgot to remove the observer, so the second time my code was performing the pop view controller twice, hence the warning message "nested pop animation ..."
Hi there and thank you in advice for your help. I have a really strange problem while working with ViewControllers in Xcode4. First of all I have to say that I'm not using storyboards and I prefer to create any UI element programmatically. So I've set a UIButton and I want that, when pressed, it brings me to a new view controller. This is the code I'm using for a button:
-(void)settingsAndExportHandle:(UIButton *)buttonSender {
SettingsViewController* settingView = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController" bundle:nil];
settingView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:settingView animated:YES];
}
This buttons is initialized and allocated in the viewDidLoad method of the RootViewController. I want to switch to the other view controller (in this case SettingsViewController) when I press the button.
The strange thing is that when I press the button, the animation that flips the controllers goes well, but when it finishes I obtain the EXACT same things that I had on the RootViewControllers (same custom views, same buttons, same all!). The question is: what I'm missing?? I have to say that I use ARC (automatic reference counting) so I can't release or dealloc the views and buttons I've created on my RootViewController.
Any help will be appreciated. Thank you all!
Pushing and and modally presenting view controllers does not deallocate the view controller that presented them. It simply adds the additional view controller to the stack. You'll need to implement a callback method so that when the user hits the button to flip back to root view controller, your settings view controller lets the root view controller know what's about to happen so you can call a method you've written to reset the interface back to whatever state you need it at. You may also be able to use viewWillAppear: but that's a little messy.
However, according to the Apple Human Interface Guidelines, the user expects that when they push a view controller or modally present it, the view controller they were on will save state and be exactly the way they left it when they came back. It's disconcerting and annoying when state is not preserved while in a navigation controller context. It is especially annoying when it's modally presented.
Think about this - A user is in a hypothetical Mail app. They start typing out an email and set a font size and a color. They tap on the add attachment button, which brings up a modal view controller that allows them to select a picture. They select the picture and the modal view is dismissed, and in your implementation, the mail composing interface would have reset and the email content would be gone or at the very least the selected font size and color would be back to the default. That's not a good experience.
I have a UINavigationController within one of the tabs of a UITabBarController.
I now present a new view controller (let’s call it Steve) over the whole app (using presentViewController:animated:completion:).
Then, I simulate low memory.
After dismissing Steve (using dismissViewControllerAnimated:completion:), I can now see that the UINavigationController’s view is gone; within the tab; only an empty white area is seen!
Why is this? I have tried calling the view methods on all imaginable controllers upon Steve’s dismissal, but the contents of the tab still stay empty (white).
The strange thing is this: If I click on another tab, and click back on the original tab, the contents (the navigation controller) shows just fine again. Is the tab bar controller doing something special to force the view to display?
UPDATE: I was able to “fix” my issue with this terrible code, just before dismissing Steve:
[[[[[self tabBarController] view] subviews] objectAtIndex:0]
addSubview:[[self navigationController] view]];
What this does is that it finds the subview of the tab bar controller which is not the tab bar (i.e. the top view), and then adds the navigation controller’s view to be its subview.
This is of course terrible, because it makes internal assumptions about the subview structure of the tab bar controller’s view.
If someone has any better solutions, please let me know about them.
When your app receives a memory warning, one of the first thing it will do is drop the view hierarchies of any view controllers that have loaded views but are not currently visible (like your UINavigationController). Most likely, whatever view controller is at the top of your navigation stack is having its views dropped but not reloading them when it reappears.
Always put your view construction code in -loadView or -viewDidLoad and not in -init. That way, the view controller will reconstruct your view if it's been dropped due to a memory warning.
(P.S.: The reason your hack works is the bit where you call [[self navigationController] view], which in turn calls -loadView on the top VC in the stack, forcing it to reconstruct its view.)
In my app delegate I have a navigationController property.
In my first view I have some buttons and tapping them will make another view appear when it is pushed on navController.
In this new view there is another button to open a UITableViewController by pushing it on the navController.
The problem is in the last view, UITableViewController, in fact in viewDidLoad, if I have no data, I try to pop it off the navigationController but my app crashes.
However, if I connect the pop to a button it works great.
I reference my app delegate instance in order to popViewControllerAnimated:, so what is the problem?
I'm not sure what's wrong with the code, can you post your viewDidLoad method?
Also, is it possible to check whether your table will have data BEFORE you push the tableView onto the nav stack? That would be a much cleaner UI, rather than showing and then immediately popping a view. If there is no data, disable the button that launches the table view.