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.
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.
The Apple guy in the What's new in Cocoa Touch WWDC video said that the new large-title navigation bar will magically hook into the top-level scroll view of the underlying view controller and collapse/expand itself automatically while scrolling up and down. (And by "magically", he probably meant that they failed to monkey patch this functionality into the already embarassing UINavigationController-UINavigationBar-UINavigationitem APIs in a usable way, so they had to resort to hooking into some heuristically chosen scroll view behind the scenes)
Even though I was prepared that this "automatic" collapse/expand wouldn't work if I deviate the slightest from the basic UINavigationController + UITableView/UICollectionView setup, it seems that even in this simplest case it doesn't work as expected.
Here's what I have:
A UITabBarController which contains a UINavigationController, which contains a UIViewController, which has a UITableView as its view. Tapping the first cell in the table will push a second view controller on the navigation stack:
No code, just the storyboard.
I've checked "Prefers large titles" for the navigation bar to activate large titles. Now, if I run the app and scroll up/down on the table view, the navigation bar stays the same - large - size; it doesn't collapse:
However, I've found that if I set the second view controller's navigation item to use the small navigation bar (by setting "Large Title" to the value "Never"), then if I open that page and navigate back, the interactive collapse magically starts working on the first page:
Am I missing something here, or is this feature not working properly? Here's the sample project I'm using: https://github.com/tzahola/iOS-11-Large-Title-Navigation-Bar
And by the way, I'm using the officially released iOS 11, not the betas.
2017-09-23 Update: I've sent a bug report to Apple, and opened a ticket on openradar.me: http://www.openradar.me/radar?id=5017601935671296
If there is any other view in addition to tableView, also make sure tableView is on the top of that view(s), right under the Safe Area:
Good news! I've just figured out that if I set "Large Titles" to "Never" on the storyboard, and then set it via code, then it works:
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.largeTitleDisplayMode = UINavigationItemLargeTitleDisplayModeAutomatic;
}
Seems like Apple forgot to handle the case when the navigation item has its largeTitleDisplayMode set via the Interface Builder.
So until they fix this issue, leave "Large Titles" as "Never" on storyboards, and set them via code in viewDidLoad.
You just need to do that to the first view controller. Subsequent view controllers honor the value in storyboard.
Or instead of changing anything in storyboard, do this:
override func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 11.0, *) {
self.navigationItem.largeTitleDisplayMode = .never
self.navigationItem.largeTitleDisplayMode = .always
}
}
No matter which language!
This is because large titles on navigation item decides whether or not to collapse on the basis of large title behaviour on previous screen navigation item title.
Make sure that addSubview(tableView) placed before others addSuview(someview)
Year 2020, iOS 13.0, this WAS NEVER mentioned here. I literally spent an hour or two for this.
Issue: Large title won't collapse when doing layout programmatically using Snapkit (an autolayout framework)
Solution: SETUP YOUR VIEWS (including navigationController stuff and tableView) inside loadView() NOT in viewDidLoad().
#TamasZahola #mohamede1945
Guys I had the same problem. I was able to resolve this issue by adding following snippet on my first View Controller of Navigation Controller
navigationController?.navigationBar.prefersLargeTitles = true
It's an odd bug. The fix is to toggle OFF prefersLargeTitles in the storyboard and to set this in viewDidLoad of your nav controller's root vc:
navigationController?.navigationBar.prefersLargeTitles = true
TableView of its container should be at the top of ViewController's view hierarchy (RootView on screenshot). Otherwise it won't work.
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.
As someone who usually used separate xibs in the past I thought I'd give storyboard a go as it seemed a lot simpler to use and much easier to develop with. I've been writing an application where the essential set up is this:
At the top of all this is a UINavigationController (first level). Then I have Multiple UIViewControllers (second level) with buttons in them which you can tap to switch between the second level UIViewControllers.
However a problem occurs when I start switching between the second level UIViewControllers. I first thought this was an initialisation problem with the NSMutableArrays because in my code I have a NSTimer set to loop periodically and found when I set a breakpoint during it, when I went forward to the next timer tick event there appeared to be different instances of the same NSMutableArrays and it seemed a gamble to try and insert new values into these array with it sometimes working, sometimes not (as it may or may not insert into the correct instance).
Then, looking at the memory usage under Debug Navigator I found the issue. Each time I "switched" between the UIViewControllers a new UIViewController was being initiated, along with all new variables.
The code I am using to switch between them is
-(void) perform {
[[[self sourceViewController] navigationController] pushViewController:[self destinationViewController] animated:NO];
}
Or essentially a push segue transition. This also explains why when I tried to switch back to my view, the data on that view was lost as it is a complete new view.
Does anyone know how to switch between multiple ones of these UIViewControllers (say 5) essentially like a UITabViewController would except without the tab bar being present?
First option you can do this: You can use a tabbarcontroller for switching viewcontroller and hidden the tabbar. Then on buttonclick setthe tabbar index.
Second option you can do this: Create one more view controller and in this viewcontroller subview the all switching viewController and when you want to switch viewcontroller just bring that viewcontroller view to front by delegate.
Do you need the navigation bar and other features provided by your top level navigation controller?
If not, you could use a UIPageViewController instead.
You set up all your second level view controllers and then just have to tell the page view controller which one to display.
If you implement the associated delegate methods, it will automatically provide swipe gestures to switch between them and nice animations to get them on and off screen.
You can also get it to put a UIPageControl at the bottom showing a dot for each VC with the dot for the current VC highlighted.
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