Top layout guide moves underneath navigation bar after pushing search results - ios

This one has kept be up a few days. I think the easiest way to illustrate my issue is with this 10 second gif.
Description
As you can see, when you go back after pushing to a search result, the segmented top bar disappears when you go back, but when I switch to the tab with "Tise" in the header and back, it resets and works properly.
As seen in the below screenshot, my issue is that the top layout guide gets offset underneath the navigation bar, which makes the segmented bar hide underneath it.
Code
My search controller is an extremely normal implementation.
/* Search controller */
let exploreSearchController = StandaloneExploreSearchResultController.initFromStoryboard(type: .top)
searchController = UISearchController(searchResultsController: exploreSearchController)
searchController?.searchResultsUpdater = exploreSearchController
searchController?.delegate = self
searchController?.searchBar.searchBarStyle = .minimal
searchController?.searchBar.isTranslucent = false
searchController?.searchBar.backgroundColor = .clear
searchController?.hidesNavigationBarDuringPresentation = false
searchController?.dimsBackgroundDuringPresentation = false
searchController?.searchBar.tintColor = #colorLiteral()
navigationItem.titleView = searchController?.searchBar
definesPresentationContext = true
and I push the result controllers in StandaloneExploreSearchResults with
presentingViewController?.navigationController?.pushViewController(viewController, animated: true)
For every new view controller, I update the navigation bar style, which I suspect might be triggering it. If I disable this function, I get different offset bugs, as seen in the following gif.
func updateNavigationBarStyle(viewController: UIViewController) {
let style = (viewController as? NavigationControllerStyling)?.preferredStyle() ?? .default
print(#file.components(separatedBy: "/").last!,":",#line,"-",#function, viewController.classForCoder)
//Showhide
UIApplication.shared.setStatusBar(hidden: style.statusBar.hidden, style: style.statusBar.style)
setNavigationBarHidden(style.hidden.hidden, animated: style.hidden.animated)
navigationBar.setCustomShadow(hidden: style.shadowHidden)
//Colors
navigationBar.tintColor = style.tintColor
navigationBar.barTintColor = style.barTintColor
navigationBar.backgroundColor = style.backgroundColor
navigationBar.setBackgroundImage(style.backgroundImage, for: .default)
navigationBar.titleTextAttributes = style.titleTextAttributes
navigationBar.isTranslucent = style.translucent
navigationBar.hairlineImageView?.isHidden = true //Always hide the native shadow
}
Question
Is there a way to either force the auto layout reload that switching tabs triggers (I've tried all the methods I could find with no success). or fix the bug somehow?

Well, that solved it. I guess setting the colors and/or images somehow fiddled with the opaque property.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
extendedLayoutIncludesOpaqueBars = true
}

Try this code in viewDidLoad -
self.edgesForExtendedLayout = []

Related

Black Navigation Bar covering image view in collection view header

I have a collection view header who's background contains an image. What I am trying to do is allow for the image to be the background of the navigation controller.
What I have now
This is what I am trying to achieve
I have tried a lot of things so far. I made the navigation bar translucent. I adjusted the edges for extended layout, and I have set the property of navigation controller to be under opaque bars.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
navigationController?.navigationBar.isHidden = false
navigationController?.navigationBar.isTranslucent = true
tabBarController?.tabBar.isHidden = false
tabBarController?.tabBar.barTintColor = UIColor.white
tabBarController?.tabBar.tintColor = UIColor.lightWetAsphalt
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController!.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.backgroundColor = UIColor.clear
self.edgesForExtendedLayout = []
collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentBehavior.never
}
Note: If i hide the navigation controller, the image view goes under the status bar perfectly fine. For some reason, when I don't hide the navigation bar, thats when it brings up this black view

Smooth disappearance of iOS 11 search bar

I am running into a small problem, I implemented the new iOS 11's style search bar in my app, and I noticed that it disappeared with a slightly different animation from the one in Messages for example. It's faster and less smooth.
Anyone has ever stumble upon this "problem" ?
Here is the code I use :
searchController.searchResultsUpdater = self
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.delegate = self
if #available(iOS 11.0, *) {
navigationItem.searchController = searchController
} else {
tableView.tableHeaderView = searchController.searchBar
searchController.searchBar.barTintColor = .white
searchController.searchBar.layer.borderColor = UIColor.white.cgColor
searchController.searchBar.layer.borderWidth = 1
}
definesPresentationContext = true
searchController.searchBar.placeholder = "all_search".localized
EDIT:
I don't know if it will help you, but I am scrolling at a normal pace .
Thanks
Adding
self.extendedLayoutIncludesOpaqueBars = true
to my viewDidLoad solved the issue, your navigation bar must not be translucent and note that extendedLayoutIncludesOpaqueBars = true is being attributed to my main view which holds the tableview.
This happens when your table view doesn't go all the way to the top of the view. Make sure your table view is "behind" the navigation bar and uses extended edges and extend under opaque edges if your navigation bar is opaque.
Try this, it fixes it for me. I used a different UIViewController as the searchResultsUpdater and just set extendedLayoutIncludesOpaqueBars as true.
searchResultsUpdater.extendedLayoutIncludesOpaqueBars = true
searchController.searchResultsUpdater = searchResultsUpdater
UIView.animate(withDuration: 1, animations: {
//your codes to implement
}, completion: nil)
change withDuration: in seconds

iphone x: keep search bar within safe zone

Upgrading our application to support iPhone X. How can I add a search bar to the header of a table view and have it within the safe zone? Here is how we currently build the search bar.
let searchController = UISearchController(searchResultsController: nil)
func buildSearchBar() {
self.searchController.searchResultsUpdater = self
self.searchController.hidesNavigationBarDuringPresentation = false
self.searchController.dimsBackgroundDuringPresentation = false
self.searchController.searchBar.sizeToFit()
self.tableView.tableHeaderView = searchController.searchBar
self.definesPresentationContext = true
}
This topic is discussed explicitly in Building Apps for iPhone X video. (Designing for iPhone X also a good video.)
Bottom line, Apple suggests using navigation controller and showing it there:
let searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.obscuresBackgroundDuringPresentation = false
if #available(iOS 11, *) {
navigationItem.searchController = searchController
searchController.isActive = true
} else {
present(searchController, animated: true)
}
(By the way, even in the absence of a navigation controller, present-ing the search controller, rather than setting it to be the table header, can prevent it from scrolling out of the safe area.)
Unclear what you mean by "within the safe zone". The table view can scroll, so the search bar is not necessarily "within" any part of the screen; it can be scrolled up behind the sensor area and on beyond.
You'll notice, however, that the native apps do not put the search bar as the header of the table. They put it in the navigation bar. You should do the same. Put the search bar into the navigation bar by setting the searchController of the navigationItem.

Add UISearchBar to UINavigationBar with UIBarButtonItem

In my app, I used to have a search bar in the header view of my table view. However, I have added a search bar button item, and when a user taps it, I want a search bar to animate across the navigation bar, and the user should be able to search. This is kind of like the search bar in the Twitter iOS app. here is the code for my UISearchController:
self.searchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.hidesNavigationBarDuringPresentation = true
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
//self.tableView.tableHeaderView = controller.searchBar
self.definesPresentationContext = true
controller.searchBar.returnKeyType = .Search
controller.searchBar.delegate = self
return controller
})()
Here is how my UINavigationBar looks like right now:
How would I go about doing this?
You're almost there. You need to do four things:
searchController.hidesNavigationBarDuringPresentation = false
navigationItem.titleView = searchController.searchBar
hide all the current UIBarButtonItems you have in the navigation bar
searchController.searchBar.becomesFirstResponder()
That is, you setup your UISearchController so it doesn't hide the navigation bar, as the UISearchBar is gonna be displayed there.
Then, when your IBAction runs, you do something like:
navigationItem.hidesBackButton = true
navigationItem.titleView = searchController.searchBar
navigationItem.rightBarButtonItem = nil
searchController.searchBar.becomeFirstResponder()
That guarantees the UISearchBar will use the entire UINavigationBar when it becomes the first responder. You also get the UISearchBar animation, which does a good job in hiding the unanimated removal of the UIBarButtonItems.
You will need to implement the UISearchBarDelegate (or if you prefer UISearchControllerDelegate) to restore the original navigation bar state once the user is done with the search.
One very important detail is that in order for your UISearchBar to be editable in the titleView, no other view controller can be set with definesPresentationContext = true at the time yours is pushed.

UISearchBar in UISearchController Does Not Disappear

I AM NOT USING STORYBOARD SEGUES.
When I use UISearchController to have a search bar at the top of my table view, I get extremely strange behavior. Is there documentation on how I'm supposed to handle the search bar when a view dismisses? When I switch to a new view controller via an animation or push one on a nav stack, the bar is stuck in its spot until I hit the "Cancel" button.
See a video of what's happening in this short clip:
https://www.youtube.com/watch?v=6G7xFMENm_o&feature=youtu.be
This is the code, in the view controller, that sets up search bar:
var s: UISearchController!
private func configureSearching() {
s = UISearchController(searchResultsController: nil)
s.searchResultsUpdater = self
s.dimsBackgroundDuringPresentation = false
s.searchBar.searchBarStyle = .Minimal
s.hidesNavigationBarDuringPresentation = false
tableView.tableHeaderView = s.searchBar
s.searchBar.sizeToFit()
}
you should add the following line in viewDidLoad
self.definesPresentationContext = true

Resources