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?
Related
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)
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.?
I have a table view that I have added a search controller in to by putting the following in to my table views class which I made sure to add UISearchBarDelegate in the class definition.
let searchDisplay = UISearchController(searchResultsController: nil)
Then in my viewDidLoad function I entered this:
searchDisplay.searchResultsUpdater = self
searchDisplay.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
tableView.tableHeaderView = searchDisplay.searchBar
I then have functions that get the required data depending on what has been searched.
Also added this after the class but in the same file:
extension AllTableViewController: UISearchResultsUpdating{
func updateSearchResultsForSearchController(searchDisplay: UISearchController) {
filterContentForSearchText(searchDisplay.searchBar.text!)
}
}
As I say in the title the code all seems to run swimmingly in the Simulator but when I run it on a device the search bar just doesn't appear. No different messages appear in the output box so I don't really know where to start.
Have you tried a sizeToFit call on the search bar? – keithbhunter Jun 30 at 13:43
I defined a UISearchController instance like this:
let searchController = UISearchController(searchResultsController: nil)
but cannot find a way to get a reference to its search results table view.
previously using UISearchDisplayController it's easy as:
self.searchDisplayController?.searchResultsTableView.reloadData()
p.s. I know that if I define it like:
let searchController = UISearchController(searchResultsController: aTableViewControllerInstance)
then the search results table view will be aTableViewControllerInstance.tableView but in my case I didn't use a table view controller.
When you have the following line:
let searchController = UISearchController(searchResultsController: nil)
This is not saying that there is no search results controller, it is saying the search results controller is the same view controller as in which it appears. Therefore the results tableView is your current view controller's tableView (ie. self.tableView).
Have you set searchResultsUpdater? It is here you need to filter as appropriate, and so you will have the results available.
A good example of what you want to do is here.
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.