UISearchController in-accessible - uitableview

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.

Related

Cannot find search bar in UI tests

I have a search controller that is created this way:
let searchController = UISearchController(searchResultsController: nil)
let searchBar = searchController.searchBar
searchBar.isAccessibilityElement = true
searchBar.accessibilityIdentifier = "ComplaintSearchBar"
searchBar.accessibilityTraits = .searchField
Later the search controller is added to a view controller and its search bar becomes part of the hierarchy. I am trying to test the search bar's existence in a UI test:
let searchBar = self.app.searchFields["ComplaintSearchBar"]
XCTAssert(searchBar.waitForExistence(timeout: 2.0))
But the test keeps failing, it doesn't find the search bar. I am interested in the search field more than the search bar, but the problem is that in iOS 12 and lower there is no way (expect for a hack, using valueForKey) to get the search field. Any convenient solution?

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

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

How Make SearchBar Like Iphone Setting

Hi Thanks For answers in advance I Have 2 Question First How to make search bar present like setting when nothing is searched yet the background shows the setting and second how is it from static tableview show the search result
searchController = UISearchController(searchResultsController: nil)
searchController?.searchBar.delegate = self
searchController?.dimsBackgroundDuringPresentation = true
searchController?.searchResultsUpdater = self
navigationItem.searchController = searchController
If I understood your question correctly, you have an empty UITableView, and you want to have a search bar when no search has been performed yet. Then, you want to have the search results appear in that table view.
First, I would suggest always having the search bar on top of the table view so that users can perform another search after the first one. But if that is not your goal, you could have the following:
var didPerformSearch: Bool = false
then, when the user performs the first search, set it to true. Then have :
if didPerformSearch == true {
yourSearchBar.isHidden = true
}else{
yourSearchBar.isHidden = false
}
Also, your results table view HAS to be dynamic, because the number of search results and the search results themselves will differ depending on the search.
So, use a dynamic table view and a UITableViewDelegate and UITableviewDataSource or a UITableViewController to show your search results, which I can't show you how to do because I don't know how you get your search results.
Hope I helped!
EDIT :
Okay so after reading your comments I actually understand what you want to do.
You could have a table view for search results on top of your ViewController with resultsTableView.isHidden = true.
Then, when the user taps the search bar, you would set resultsTableView.isHidden = false
OR
You could even animate it like this :
UIView.animate(duration: 0.2) {
resultsTableView.alpha = 1
}
(set it to 1 to show it, to 0 to hide it)

UISearchController :how can I use obscuresBackgroundDuringPresentation behaviour as true/false

I am using UISearchController and results controller will be the same.
searchController = UISearchController(searchResultsController: nil)
searchController?.searchResultsUpdater = self
searchController?.searchBar.delegate = self
searchController?.obscuresBackgroundDuringPresentation = true
// This will allow users won't able interact with tableview when search is active.
As I have told already if user search for something I will show the results in same view controller so when search starts "text did change" I want to disable this behavior. How can I achieve this.?

UISearchController not properly dismissing when going out of scope [duplicate]

This question already has answers here:
UISearchController persisting after segue
(2 answers)
Closed 7 years ago.
I'm building in search functionality into my app, which consists primarily of UITableViews. I have successfully added a search bar, and can search for items properly, but when I set controller.dimsBackgroundDuringPresentation = false things get all weird. The issue is, I do want this boolean to be false, since users should be able to scroll through the results and select a result to see more details.
The behavior that I'm seeing is the following: the search bar never dismisses itself, unless you press the Cancel button, meaning that when I select a cell in my table view to show the details of that cell, the search bar carries over into that view, as such:
I initialize my search controller as follows:
self.searchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
controller.hidesNavigationBarDuringPresentation = false
controller.searchBar.searchBarStyle = .Minimal
controller.delegate = self
self.tableView?.tableHeaderView = controller.searchBar
return controller;
})()
and while the searching itself works (updateSearchResultsForSearchController gets called, I apply my search and return an array, etc), I can't seem to use the search in any way, since if I select a cell while searching, the above picture happens, but if I press cancel, then my search is cleared. Any help would be appreciated.
you should add the following line in viewDidLoad()
definesPresentationContext = true
See the documentation for details: definesPresentationContext

Resources