Grey background in navigation bar with searchController added to navigationItem during push - ios

I have a table view in navigation controller so that I can push the detail view controller on the stack. It works fine, until I add a search controller to the navigation item, like so:
searchController = UISearchController(searchResultsController: nil)
searchController.obscuresBackgroundDuringPresentation = false
searchController.hidesNavigationBarDuringPresentation = false
searchController.searchBar.delegate = self
searchController.searchBar.tintColor = Colors.mlLabel
navigationItem.searchController = searchController
definesPresentationContext = true
It results in temporary grey background, see below:
When debugging the view hierarchy, it looks like UIViewControllerWrapperView's _UIParallaxDimmingView(selected below) is causing this, as both navigation bar and status bar are transparent.
How can I fix this?
Note: Setting the animated property in pushViewController() to false works, but I'd like to keep the animation.
Update: This seems to be issue only on iOS 13. Probably from some recent version even, as I didn't have this issue earlier.
Update 2: I've noticed the same issue on multiple places in my app now, and it's not just in combination with SearchController. Basically the _UIParallaxDimmingView sticks its nose out.

Update
Here's the code I use to go from a large title to a small title. These are properties for the large title viewcontroller, or more specific its navigation controller:
navigationController.navigationBar.prefersLargeTitles = true
navigationController.topViewController?.extendedLayoutIncludesOpaqueBars = true
Perhaps the second line above might help you?
As for pushing any view controllers, I see I've overridden the push-function from the navigation controller (as I use the navigation controller for each tab in my tabbar):
override func pushViewController(_ viewController: UIViewController, animated: Bool) {
if viewControllers.count >= 1 {
viewController.hidesBottomBarWhenPushed = true
viewController.navigationItem.largeTitleDisplayMode = .never
}
super.pushViewController(viewController, animated: animated)
}
Previous answer
I saw this a couple of times before in my life and it always had to do something with the background color of the view controller itself. If it's transparent you see this stuff when animating.
But since it's a search controller, it might be the navigation bar. Anyway, since the issue is only since iOS13, I believe the issue can be resolved using this:
searchController.searchBar.backgroundColor = UIColor.clear (or whatever color)
This new property (UISearchBar.searchTextField.backgroundColor) has been added since iOS13, so maybe this will solve it for you? :)

I've finally found a solution. One of the problems was that I've set a background color for the navbar like so:
UINavigationBar.appearance().backgroundColor = .white
So removing the above line and adding the below line to the view controller being pushed fixed it.
extendedLayoutIncludesOpaqueBars = true

Related

Navigation Bar is pushed up

I am having an issue where I have a tab bar controller with 4 tabs and they each have their own navigation controller with table view controllers as root views and when the app first loads the navigation bar of the first tab is pushed up behind the status bar.
I am pretty sure this problem has something to do with constraints but I can't seem to figure out what constraints I need to change.
Code Example
class TabBarController: UITabBarController {
....
let firstNavVC = FirstNavViewController()
let secondNavVC = SecondNavViewController()
let thirdNavVC = ThirdNavViewController()
let fourthNavVC = FourthNavViewController()
self.viewControllers = [firstNavVC, secondNavVC, thirdNavVC, fourthNavVC]
...
}
class FirstNavViwController: UINavigationController {
...
let vc = TableViewController()
self.setViewControllers([vc], animated: false)
...
}
Result when app loads
How it should look
Please add self.isNavigationBarHidden = false in your FirstNavViwController and check, it should work
Remove top constraint and add top constraint to safe area layout guide.
Use self.navigationController?.navigationBar.isHidden = false this line of code in the First ViewController of each NavigationController from tabs.

iOS 11 tableView with Style Grouped makes large title become invalid

I gave my tableViewController a large title Style programmatically:
self.navigationController?.navigationBar.prefersLargeTitles = true
and in storyboard, I made tableView "Static Cell" content, and "Grouped" Style in Attributes inspector:
But largeTitle didn't work when I ran the app, if tableView style is "Plain", it works. How can I fix it?
I'm not sure if it's your case, but for me using tableView.bounces = false prevented the large-title from working. Removing this line did the trick.
Where did you put your self.navigationController?.navigationBar.prefersLargeTitles = true. I putted it in ViewDidload and it's works properly
It's not clear to me why this occurs. Quite possibly a bug. But here is a work around. In Document Outline. Select your Navigation Controller Scene -> Navigation Bar then select Prefer Large Titles (at the top) in Attribute Inspector like so:
After making this change, if you want other view controllers to have regular / plain titles, simply add this to viewDidLoad() on that particular V.C.
navigationItem.largeTitleDisplayMode = .never
Remove title from your storyboard
In your UIViewController over viewDidLoad function:
navigationItem.title = "Search title"
navigationController?.navigationBar.prefersLargeTitles = true

difference between navigationBar.isHidden and setNavigationBarHidden

I have view controller which I am pushing from a view controller where navigation bar is hidden. But I want to show the navigation bar in destination view controller.
I tried with this statement it was not showing navigationBar.
self.navigationController?.navigationBar.isHidden = false
I tried this statement it is working
self.navigationController?.setNavigationBarHidden(false, animated: true)
I want to know what is difference?
.isHidden and setNavigationBarHidden() have different effects and outcomes. We won't be talking about the animated part.
The property of self.navigationController?.navigationBar.isHidden is an extension from UIView. The isHidden property belongs to UIView that means that navigationBar (which extends UIView) had done some overriding in isHidden causing it to have different effect and outcome compared to setNavigationBarHidden().
Example for setNavigationBarHidden(true):
where the navigationBar won't be transparent and page 1 (page with navigationBar hidden).
Example for .isHidden = true:
where the navigationBar is fully transparent and page 1 is displayed under page 2's navigationBar. Number 3 is the UIWindow.
Effect is exactly the same, but when using second version (method) you can also define animation.
When you are doing it via property - animation is off by default.
On top of that you have another option:
self.navigationController?.isNavigationBarHidden = false
More on that topic here:
https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621850-isnavigationbarhidden
If true, the navigation bar is hidden. The default value is false. Setting this property changes the visibility of the navigation bar without animating the changes. If you want to animate the change, use the setNavigationBarHidden(_:animated:)method instead.
Nope they are not the same,
self.navigationController?.isNavigationBarHidden
is a getter property (it shows you wheather the navBar is hidden or not.) It will just return a boolean value conveying the state of the NavBar weather it is hidden or not.
(try assigning its value to bool like var isHidden = self.navigationController?.isNavigationBarHidden it will give you true of false according to state to the NavBar.)
whereas
self.navigationController?.setNavigationBarHidden(false, animated: true)
is a setter propety which gives you the provision of setting the state of the navBar.
Compiler does not throw any error on self.navigationController?.isNavigationBarHidden = false
but will not do anything as you can only know the state from here.

Prevent UISearchBarController to show UINavigationBar

I'm using a UINavigationBar ALWAYS hidden (I'm using NavigationBar facilities to push ou pop views but I'm not showing it to final user), the problem is that in one of those views I have a tableView with UISearchBar. When I select the searchBar, make a search and click on it's "Cancel" button the NavigationBar appears, but I want to keep the Navigation hidden as it is.
I've tried to hidden the navigationBar one more time by willDismissSearchController or didDismissSearchController by
func willDismissSearchController(searchController: UISearchController) {
self.navigationController?.navigationBar.hidden = true
}
but it did not worked as I want.
Thank you in advance.
I've found a solution, so as it is a unusual question I'll reply for other people know the solution.
the following code did worked for me:
override func viewDidLayoutSubviews() {
self.navigationController?.navigationBar.hidden = true
}

UISearchController in-accessible

I have implemented a search screen using UISearchController and a table view. When I start searching for something, the search controller adds a view on top of the table view (although, it does nothing) and until I set the searchController.active = false, the table view is in-accessible with VoiceOver. I have tried almost everything it seems, and the only solution is to abandon UISearchController for UISearchBar. Currently, once the keyboard is shown and the search controller is active, the VoiceOver selector will go from the text field, to a bar button item, then it skips the table view and goes to the keyboard. Here is my setup of UISearchController.
searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.delegate = self
searchController.hidesNavigationBarDuringPresentation = false
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.searchBarStyle = .Minimal
searchController.searchBar.keyboardAppearance = .Dark
searchController.searchBar.showsCancelButton = false
searchController.searchBar.delegate = self
searchController.searchBar.text = prefilledSearch
searchController.view.layer.borderColor = UIColor.redColor().CGColor
searchController.view.layer.borderWidth = 1.0
searchController.view.isAccessibilityElement = false
searchController.view.hidden = true
searchController.searchBar.setShowsCancelButton(false, animated: false)
How can I get this fixed and continue to use UISearchController? currently, search is not usable with VoiceOver users in my app.
That's because underlying UITransitionView sets incorrect value for accessibilityViewIsModalSelector which traps VO within search view, which in your case is empty.
I can only think of patching this behavior by swizzling accessibilityViewIsModal on private UITransitionView.
I described the technique in a blog post I wrote:
http://www.morphineapps.com/blog/accessibility-on-ios
Relevant gists:
https://gist.github.com/pronebird/0d3c06485de50e100d1e93bcde08c94c#file-snippet-m
https://gist.github.com/pronebird/66aa70b005ed9af8d357cdc7e940542b#file-search-controller-snippet-m
I've found that the accepted answer is suboptimal, even though it might be technically correct.
If you use the obscuresBackgroundDuringPresentation (added in iOS 9.1) and set it to false, VoiceOver can access the underlying table view.
Usage:
searchController.obscuresBackgroundDuringPresentation = false
From what I've found on this page, http://www.iaccessibility.net/report/uisearching-for-accessibility-nil, the problem is that you set searchResultsController to nil which makes the original view controller display the search results. When the search controller has focus it blocks VoiceOver from accessing the search results in the original view controller. By specifying a separate results view controller, VoiceOver will work.

Resources