I am implementing an application that uses a UINavigationController. It currently shows 3 views, each a UITableViewController. The first view that is shown only has a title, while the other two have a title and prompt. All segues are created in the storyboard, which is rather straightforward:
The problem: As soon as I animate AWAY from a view that has a prompt, the animation glitches - the title (and sometimes the back button) "fly in" from the bottom, instead of from the right.
Example: https://youtu.be/N-K8piEJ1aY (recording with slow animations turned on)
Here you can see that the animation from first to second view works fine, but from second to third view is glitchy. animating back works.
This issue seems similar to Weird animations when changing NavigationItem prompt . The conclusion in that thread was that this only occurs on iOS 7, I am running on iOS 10.0/10.1, though. The issue occurs both in simulator and on the real device.
Any ideas?
The only solution I found was an absolute hack inspired by an absolute hack inspired by Catalina T. over on this post:
Either in viewWillAppear: on the appearing VC or after calling pushViewController:animated: on the navigation controller (or I'm guessing after calling performSegueWithIdentifier:sender: add the following code:
ObjC
// This is a hack that's because UINavigationBar with prompts is broken
navigationController.navigationBarHidden = YES;
navigationController.navigationBarHidden = NO;
Swift
// This is a hack that's because UINavigationBar with prompts is broken
navigationController.isNavigationBarHidden = true
navigationController.isNavigationBarHidden = false
where navigationController is a reference to the UINavigationController that's doing all the pushing (e.g. viewController.navigationController)
EDIT: It appears now there're other weird animations that occur when popping and repushing a VC, so this answer isn't a true solution. Leaving it up so as to help someone else down a similar rabbit hole.
Related
When I try to back out of my Navigation stack using either the back button or swiping back from the left side of the screen, the navigation bar changes but does not dismiss the ViewController (or, in the case of swiping, the navbar animation is not interruptible). Please see the gif below.
I'm implementing my NavigationController with storyboard. It's just a UIViewController embedded into a UINavigationController. I've tried detaching the UIViewController and reattaching it to a different NavControl, manually embedding it, removing the TabBar controller that was also embedded originally. All of these have led to the same result.
Edit: Also relevant is how I'm pushing these ViewControllers to the nav stack. To present these VCs, I'm just using navigationController?.pushViewController(vc, animated: true).
present(_: UIViewController,animated: Bool) gives a modal presentation which is not what I'm looking for.
Any ideas as to what would be causing this odd behavior?
I had the following in my rootViewController's viewDidLoad from some earlier experimentation that wasn't being used:
// Setting as delegate might not be necessary right now,
// could become useful in the future?
navigationController?.navigationBar.delegate = self
Evidently it did not become useful in the future. Seems like doing this causes the delegate to become responsible for some of the work navBar usually does for free? Removing it immediately fixed the issue.
I have a problem in that in swift when i set the UINavigationController to hidden using
navController.navigationBarHidden = true
it also stops the swipe back ability on any viewcontrollers that are pushed onto the stack. there doesn't seem to be any accepted fix, and i've tried setting the interactivePopGestureRecogniser as suggested by others, but this doesn't work any more either (i think that may have worked in swift 1?)
pls halp.
You can add your own interactive gesture and animation (called an interactive custom transition animation). It can be just like the default swipe gesture, or you can use use a different gesture and a different animation.
I modified AAPLSearchBarEmbeddedInNavigationBarViewController in Apple's UICatalog sample code so that it pushes another instance of AAPLSearchBarEmbeddedInNavigationBarViewController onto the navigation stack when a cell is selected. In the second view controller the UISearchBar set as the title view of the UINavigationBar (just like the first one) isn't tappable (unlike the first the one). This seems like a bug. How do I fix it? Here is my modified UICatalog code:
https://github.com/stevemoser/UICatalog
Also I tested with with Xcode 6 and 7. It's broken in both.
The solution is to set the first VC self.definesPresentationContext = NO when navigating away from it and making sure to call self.definesPresentationContext=YES in the view did appear so that the visible VC allows defines the presentation context.
Thanks goes to Rory McKinnel who put me on the right track.
After upgrading my project to iOS7
when I do a BACK Button and the UINavigationController goes back to the previous page, an ImageView on the top of the screen shifts down.
I use IB to do my layouts. These are my Simulated Metrics:
I have AutoLayout off. Any ideas on what the issue might be? I wasnt sure if anyone wants to see specific code and I didnt want to clutter up the question with too much code.
Updates: Based on the comment questions, I wanted to make these updates:
In no place in the application .h or .m file do I make any changes to the imageview's sizes or location.
In both the viewDidLoad and viewDidAppear I call a user-defined method called recalculateAll but their is no reference at all to any imageview sizes. Just for trying it out I commented out the entire section and ran the code and it still jumps down.
In my init I do programatically set some imageviews (you see the #132 in what appears to be a bubble) using their x and y's.
Here is a typical navigation I use for moving from the view controller to the tableviewcontroller:
GetTimeOffByType *showTimeOffReport = [[GetTimeOffByType alloc] initWithNibName:#"GetTimeOffByType" bundle:nil];
showTimeOffReport.timeOffType = #"Vacation";
[self.navigationController pushViewController:showTimeOffReport animated:YES];
These are all .xib files, no storyboarding at all. Its basically a view controller which has an embedded UINavigationController with 6 buttons. Each time a button is pressed it pushes a UITableViewController passing different parameters and showing different data. The transition I am using to get back to the original UIViewController is simply the iOS generated BACK button (so no code to show for that)
Update#2 Hopefully this will help someone solve this wierd behavior. So if I were to click on the table view cell on showTimeOffReport to get the cell detail and then using BACK navigate all the way back it doesnt jump down.
Update#3 Ok this is something I just discovered : The issue of jumping down or not is related to the translucency of the UINavigationBar. If you have a Translucent = YES it will start from the top of the window. If you have a translucent = NO it will start from the bottom of the UINavigationBar.
You might try setting the new property on UIViewController edgesForExtendedLayout to UIRectEdgeNone.
Here is a good resource that explains more about how view layouts changed in iOS 7.
See Apple Documentation
If you plan to be backwards compatible you will probably need to do some runtime checks and adjust positioning if the device is not running iOS 7.
This might help you..You can try adding UIViewControllerBasedStatusBarAppearance key and set it's value NO in your info.plist
UIViewControllerBasedStatusBarAppearance = NO
Short version:
I'm alloc/init/retaining a new UIViewController in one UIViewControllers viewDidLoad method, adding the new View to self.view. This usually works, but it seems to mess up orientation change handling of my iPad app.
Longer version:
I'm building a fairly complex iPad application, involving a lot of views and viewcontrollers. After running into some difficulties adjusting to the device orientation, I made a simple XCode project to figure out what the problem is.
Firstly, I have read the Apple Docs on this subject (a small document called "Why won't my UIViewController rotate with the device?"), and while I do believe it has something to do with one of the reasons listed there, I'm not really sure how to fix it.
In my test project I have an appDelegate, a rootViewController, and a UISplitViewController with two custom viewControllers. I use a button on the rootViewController to switch to the splitViewController, and from there I can use a button to switch back to the rootViewController. So far everything is great, i.e. all views adjust to the device orientation.
However, in the right viewController of the splitViewController, I use the viewDidLoad method to initialize some other viewControllers, and add their views to its own view:
self.newViewController = [[UIViewController new] autorelease];
[newViewController.view setBackgroundColor:[UIColor yellowColor]];
[self.view addSubview:newViewController.view];
This is where things go wrong. Somehow, after adding this view, adjusting to device orientation is messy. On startup everything is fine, after I switch to the splitViewController everything is still fine, but as soon as I switch back to the rootViewController it's all over. I have tried (almost) everything regarding retaining and releasing the viewcontroller, but nothing seems to fix it.
As you can see from the code above, I have declared the newViewController as a property, but the same happens if I don't.
Shouldn't I be adding a ViewController's view to my own view at all? That would really mess up my project, as I have a lot of viewControllers doing all sorts of things.
Any help on this would be greatly appreciated...
I had the same problem, seams resolved by removing from the parent view the "autoresize subview" option in IB.
Select the view a then: Inspector -> Attributes (first tab) -> drawing.
What I think is happening is that your new viewcontroller is getting the autorotation calls and probably not handling them. Meanwhile your old viewcontrollers and its views won't get the autorotation calls and will be stuck in whatever orientation they were in.
I can't tell, but I think what you want to do is to make a UIView and add it to your old viewcontroller, instead of making a UIVIewController and adding its view.