I am using UISearchController in iOS 8 with the following intializaiton in viewDidLoad of a view controller embedded in a tab controller
_searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
_searchBar = _searchController.searchBar;
[_searchController.searchBar sizeToFit];
_searchController.searchBar.delegate = self;
_searchController.searchResultsUpdater = self;
_searchController.dimsBackgroundDuringPresentation = NO;
_searchController.hidesNavigationBarDuringPresentation = NO;
self.definesPresentationContext = NO;
_shopsTable.tableHeaderView = _searchController.searchBar;
I've implemented
- (void) updateSearchResultsForSearchController:(UISearchController *)searchController and (void)filterContentForSearchText:(NSString *)searchText
and the search works, the tableview gets updated properly, etc.
But!
If I switch tabs while the searchcontroller is active (just tapping the search bar or with some text) to a different tab, and then go back to teh search tab, I get a blank screen with only the search bar, like this
In this case, I search for things that start with lar, which did return results and displayed them correcly. But if I switch tabs, and return to the search tab I get a blank screen like this. The only way the controller returns to its original state is if I do _searchController.active = NO. But if the user wants to keep that search active, I can't just deactivate it.
I am sure I am missing something, but since there isn't much to do in UISeachController, I can't figure out what is causing this..
Try self.definesPresentationContext = YES; instead of NO. Here is how I setup my UISearchController, but I haven't done it this way in a UITabBarController before.
func setupSearchController() {
let resultsController = UIStoryboard(name: "ATPageTableViewController", bundle: nil).instantiateViewControllerWithIdentifier("ATPageTableSearchResultsViewController") as! ATPageTableSearchResultsViewController
searchController = UISearchController(searchResultsController: resultsController)
searchController.delegate = self
resultsController.delegate = self
resultsController.cellIdentifier = ATDataSetItemTableViewCellIdentifier;
resultsController.table = self.table!
searchController.searchBar.sizeToFit()
self.tableView.tableHeaderView = searchController.searchBar
searchController.searchResultsUpdater = self
searchController.searchBar.delegate = self
definesPresentationContext = true
}
Write the below code in viewDidLoad mehtod.
self.definesPresentationContext = true
searchController.searchResultsUpdater = self
searchController.searchBar.delegate = self
searchController.dimsBackgroundDuringPresentation = false
searchController.definesPresentationContext = true
Related
I have an App that is presenting a MKMapView embedded in a UINavigationController. In the UINavigationController I have put a UISearchController. When the User touch the UISearchController it displays a UITableViewController.
It works well while I'm not adding the Scope button in the UISearchController.
Here the screenshot of the UISearchController in the UINavigationController when I start the App.
Next when I touch the UISearchController, it displays the UITableViewController and scope button.
Here we can already see there's an issue with the scope button because they are not well integrated in the UISearchController (color should be translucent)
Next, when I touch the Cancel button to go back to the Main viewController, the UISearchController is not recovering its original style
it has a dark gray border (that probably comes from the scope button).
Here's how I add the UISearchController in the Main view Controller
func initSearchController() {
let mySearchController = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("SearchControllerId") as! SearchController
self.searchController = UISearchController(searchResultsController: mySearchController)
mySearchController.theSearchController = self.searchController
mySearchController.delegate = self
// Configure the UISearchController
self.searchController.searchResultsUpdater = self
self.searchController.delegate = self
self.searchController.searchBar.delegate = self
self.searchController.searchBar.placeholder = "data.."
self.searchController.hidesNavigationBarDuringPresentation = false
self.searchController.dimsBackgroundDuringPresentation = true
self.navigationItem.titleView = searchController.searchBar
self.definesPresentationContext = true
}
this method is called in the viewDidLoad() of my Main ViewController.
Next, when the SearchController is displayed, I'm adding the scope button with the following code in my TableViewController subclass
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
// Mandatory to make sure the TableView is displayed when the search field is empty
// when user touch it.
view.hidden = false
var rect = delegate.searchController.searchBar.superview?.frame
rect?.size.height = 88
self.delegate.searchController.searchBar.scopeButtonTitles = ["one", "two", "three"]
self.delegate.searchController.searchBar.showsScopeBar = true
self.delegate.searchController.searchBar.superview?.frame = rect!
}
and the following code is executed when search is closed
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
var rect = delegate.searchController.searchBar.superview?.frame
rect?.size.height = 44
self.delegate.searchController.searchBar.superview?.frame = rect!
self.delegate.searchController.searchBar.showsScopeBar = false
self.delegate.searchController.searchBar.scopeButtonTitles = nil
}
As you can see I have severals issues with this code.
Scope buttons are not displayed correctly and I'm unable to add them with a nice animation
When user exits the search Scope buttons are removed but it impacts the background of the UISearchController
Can you tell me what I'm doing wrong and what should I do to integrate correctly Scope Button in UISearchController?.
I have found examples but only when the UISearchController is not embedded in the UINavigationController.
Thanks for your help!
Sébastien.
You should try using the searchBar.scopeButtonTitles in your instance of UISearchController:
func initSearchController() {
let mySearchController = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("SearchControllerId") as! SearchController
searchController = UISearchController(searchResultsController: mySearchController)
// Set Scope Bar Buttons
searchController.searchBar.scopeButtonTitles = ["one", "two", "three"]
// searchController.searchBar.showsScopeBar = true //if you want it always visible
// Configure the UISearchController
searchController.searchResultsUpdater = self
searchController.searchBar.sizeToFit()
tableView.tableHeaderView = searchController.searchBar
searchController.delegate = self
searchController.searchBar.delegate = self
searchController.searchBar.placeholder = "data.."
searchController.hidesNavigationBarDuringPresentation = false
searchController.dimsBackgroundDuringPresentation = true
definesPresentationContext = true
}
No need to show or hide your scopeButtons in willAppear/didDisapear. This is set by: searchController.searchBar.showsScopeBar = true
in my swift 2 app i have a table view with a search bar:
But if tap on the search bar, my navigation bar and the search bar will be hidden.
This is my code which is in the viewDidLoad
self.resultSearchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
controller.hidesNavigationBarDuringPresentation = true
self.MyTable.tableHeaderView = controller.searchBar
return controller
})()
At the beginning i also get this message:
Attempting to load the view of a view controller while it is
deallocating is not allowed and may result in undefined behavior
()
My Question is, where is my mistake? :/
from this tutorial you can use this code to solve the problem.
self.navigationController!.navigationBar.translucent = false
searchController!.hidesNavigationBarDuringPresentation = false
// This makes the view area include the nav bar even though it is opaque.
// Adjust the view placement down.
self.extendedLayoutIncludesOpaqueBars = true
self.edgesForExtendedLayout = UIRectEdge.Top
You have to modify your code with the below if you want to make it worked perfectly:
self.resultSearchController = UISearchController(searchResultsController: nil)
self.resultSearchController.searchResultsUpdater = self
self.resultSearchController.searchBar.delegate = self
self.definesPresentationContext = true
self.resultSearchController.dimsBackgroundDuringPresentation = false
self.resultSearchController.hidesNavigationBarDuringPresentation = true
if #available(iOS 11.0, *) {
self.navigationItem.searchController = self.resultSearchController
} else {
self.tableView.tableHeaderView = self.resultSearchController.searchBar
}
I have created a searchBar programatically and added it to the navigation bar tile view. This is my code:
UISearchController *searchController = [[UISearchController alloc] initWithSearchResultsController:self];
searchController.dimsBackgroundDuringPresentation = YES;
// Use the current view controller to update the search results.
searchController.searchResultsUpdater = self;
//Setting Style
searchController.searchBar.barStyle = UIBarStyleBlack;
searchController.searchBar.barTintColor = [UIColor colorWithRed:49.0/255.0 green:49.0/255.0 blue:61.0/255.0 alpha:1.0];
searchController.searchBar.backgroundImage = [UIImage imageNamed:#"BG"];
searchController.searchBar.placeholder = #"Search Artists, Songs, Albums etc.";
searchController.searchBar.keyboardAppearance = UIKeyboardAppearanceDark;
self.definesPresentationContext = YES;
self.navigationItem.titleView = searchController.searchBar;
searchController.delegate = self;
searchController.searchBar.delegate = self;
[searchResultsTableView reloadData];
-(BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar{
NSLog(#"Halp.jpg");
return YES;
}
This above method along with all other methods aren't being called. My header looks like this:
<UISearchResultsUpdating, UITableViewDelegate, UISearchControllerDelegate, UISearchBarDelegate, UITableViewDataSource>
The problem is probably related to this line:
searchController.searchBar.delegate = self;
I suspect that the UISearchController sets itself as the UISearchBar's delegate, so setting it yourself messes things up in some way.
I'm trying to use the new UISearchController in my tableViewController.
However I'm a bit confused on how it can move up in the navigationController when I press the searchBar like it did with the old searchDisplayController?
At the moment it just stay in the tableHeader.
Here is my code:
self.teamSearchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchBar.searchBarStyle = UISearchBarStyle.Minimal
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
controller.searchBar.showsScopeBar = true
self.tableView.tableHeaderView = controller.searchBar
return controller
})()
Controller:
When I click on searchbar:
You can place the UISearchBar of UISearchController in the navigation bar instead of table header
self.searchController.hidesNavigationBarDuringPresentation = NO;
self.searchController.searchBar.searchBarStyle = UISearchBarStyleMinimal;
// Include the search bar within the navigation bar.
self.navigationItem.titleView = self.searchController.searchBar;
self.definesPresentationContext = YES;
Swift version:
self.searchController.hidesNavigationBarDuringPresentation = false
self.searchController.searchBar.searchBarStyle = UISearchBarStyle.Minimal
// Include the search bar within the navigation bar.
self.navigationItem.titleView = self.searchController.searchBar
self.definesPresentationContext = true
It has to do with the navigation bar.
func willPresentSearchController(searchController: UISearchController) {
self.navigationController?.navigationBar.translucent = true
}
func willDismissSearchController(searchController: UISearchController) {
self.navigationController?.navigationBar.translucent = false
}
If you do this, then you will be able to add it to the table view header AND get the baked-in search controller animation!
I programmatically created a UISearchController, and set the scope button titles in viewDidLoad
UITableViewController *searchResultsController = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain];
searchResultsController.tableView.dataSource = self;
searchResultsController.tableView.delegate = self;
[searchResultsController.tableView registerNib:musicNib forCellReuseIdentifier:#"MusicCell"];
self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
self.searchController.searchResultsUpdater = self;
UISearchBar *searchBar = self.searchController.searchBar;
searchBar.scopeButtonTitles = #[#"Album", #"Artist", #"Song"];
searchBar.showsScopeBar = YES;
searchBar.selectedScopeButtonIndex = 0;
searchBar.delegate = self;
self.tableView.tableHeaderView = self.searchController.searchBar;
But when I search in search bar when view loaded. the scope bar don't show up. The second I search in search bar, the scope bar shows. What's going on?
Try this:
searchBarDisplayController.searchBar.showsScopeBar = NO;
searchBarDisplayController.searchBar.scopeButtonTitles = nil;
Based on your comment, put the above code in searchDisplayControllerWillBeginSearch: delegate method. That should work.
searchController.delegate = self
// in the delegate...
func willPresentSearchController(_ searchController: UISearchController) {
searchController.searchBar.showsScopeBar = true
searchController.searchBar.sizeToFit()
}
func willDismissSearchController(_ searchController: UISearchController) {
searchController.searchBar.showsScopeBar = false
searchController.searchBar.sizeToFit()
}
For iOS 16 and upper try this:
searchController.scopeBarActivation = .onSearchActivation
You can remove searchBar.showsScopeBar = YES;