iOS 11 I'm having a UITableViewController with a UISearchController on the table's headerview using the following code :
if(searchController == nil)
{
searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
searchController.dimsBackgroundDuringPresentation = false;
searchController.searchResultsUpdater = self;
searchController.searchBar.delegate = self;
self.definesPresentationContext = NO;
searchController.delegate = self;
}
self.tableView.tableHeaderView = searchController.searchBar;
[self.tableView setContentOffset:CGPointMake(0,searchController.searchBar.bounds.size.height) animated:YES];
When I run the app, the behavior I want is perfectly working for the tableview with rows more than the height of the device screen but on the case of tableview having only a few number of rows, the search bar is dropping a little bit down from the navigation bar.
When there are few cells on the tableview, the search bar drops down as in this picture
When there are more cells on the tableview, the search bar doesn't drop down
On iOS 11 the behaviour of UISearchController with tableView header has changed, now it a part of the navigationItem and you dont need the tableView. So you must check if iOS >= 11 and do the following
if (#available(iOS 11.0, *)) {
self.navigationItem.searchController = searchController;
// ToDo : dont forget to hide the tableView
// ...
} else {
self.tableView.tableHeaderView = searchController.searchBar;
[self.tableView setContentOffset:CGPointMake(0,searchController.searchBar.bounds.size.height) animated:YES];
}
Related
In my app, I have a navigation controller (N1), controlling a tableview controller (T1) with a search bar.
When the search bar becomes active, a new navigation controller (N2) is presented from the storyboard to display the search results. (see image)
This worked perfectly fine, until iOS 11, where the search bar is moved from the tableview header to the navigation bar.
A partial solution is to differentiate between OS versions, as follows:
-(void)initSearchController{
UINavigationController *searchResultsController = [[self storyboard] instantiateViewControllerWithIdentifier:#"TableSearchResultsNavController"];
self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
self.searchController.searchResultsUpdater = self;
self.searchController.hidesNavigationBarDuringPresentation = NO;
if (#available(iOS 11.0, *)) {
self.navigationItem.searchController = self.searchController;
//searchResultsController.navigationItem.searchController = self.searchController;
} else {
self.tableView.tableHeaderView = self.searchController.searchBar;
}
}
However, because of the new position of the search bar in iOS 11, as soon as the search results are displayed, the search box disappears, since it is part of the navigation bar that has been replaced by the alien storyboard navcontroller.
I also modified a method, that is called when the search bar becomes active, as follows, but still the search bar disappears:
// Called when the search bar becomes first responder
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
NSString *searchString = self.searchController.searchBar.text;
[self updateFilteredContentForSearchString:searchString];
if (self.searchController.searchResultsController) {
UINavigationController *navController = (UINavigationController *)self.searchController.searchResultsController;
SearchResultsTableViewController *vc = (SearchResultsTableViewController *)navController.topViewController;
self.searchController.dimsBackgroundDuringPresentation = false;
//my attempt, to no avail
if (#available(iOS 11.0, *)) {
vc.navigationItem.searchController = self.searchController;
} else {
vc.searchController=self.searchController;
}
vc.searchResults = self.searchResults;
[vc.tv reloadData];
}
}
What would be the approach to solve this? I want the app to remain compatible with pre-11 OS's (at least iOS10).
Do I have to completely rework this mechanism (if yes, how?), or is there just a simple line of code that would simply tell the controller N2 to also display the search bar?
Thanks for your insights
I am trying to get the new iOS-11 searchBar approach to work, but don't manage. The searchBar shows up, but is shown below the left bar button, instead of next to it:
It is the same in landscape mode.
The code that I am using is:
self.searchResults = [[SearchResultsTable alloc] init];
self.searchResults.delegate = self;
searchController = [[UISearchController alloc] initWithSearchResultsController:self.searchResults];
searchController.searchResultsUpdater = self.searchResults;
searchController.hidesNavigationBarDuringPresentation = NO;
self.definesPresentationContext = YES;
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh
target:self
action:#selector(swapToListView:)];
if ([self.navigationItem respondsToSelector:#selector(setSearchController:)]) {
// only available from IOS-11 onwards
self.navigationItem.title = nil;
self.navigationItem.titleView = nil;
[self.navigationItem setSearchController:searchController];
} else {
// Fallback on earlier versions
self.navigationItem.titleView = searchController.searchBar;
}
The old code works fine on pre-iOS-11 systems, but has other problems on iOS-11, so I prefer to use the new approach.
Anybody knows what I am doing wrong here?
If you want to put search bar next to left navigation item then make your search bar navigationItem's titleView regardless of iOS version, and don't use UINavigationItem's searchController property.
I added a UISearchBar to my initial UIViewController and everything works fine. However when I go to add the same UISearchBar, the same way to another ViewController that's pushed ontop of the first one, nothing seems to happen when I click into the searchBar. No delegate method is fired, no keyboard comes up, nothing.
This is how I'm adding it to the navigationBar:
- (void)viewDidLoad {
[super viewDidLoad];
UITableViewController *searchResultsController = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain];
searchResultsController.tableView.dataSource = self;
searchResultsController.tableView.delegate = self;
self.searchResults = [NSMutableArray array];
self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
self.searchController.searchResultsUpdater = self;
self.searchController.hidesNavigationBarDuringPresentation = NO;
self.searchController.searchBar.placeholder = NSLocalizedString(#"Search, eh?", nil);
// Include the search bar within the navigation bar.
self.navigationItem.titleView = self.searchController.searchBar;
self.definesPresentationContext = YES;
}
Like I said it works in the first UIViewController, am I missing something in the other 2-3 viewControllers I've tried adding this too? I don't see why the searchBar shows up in the navBar but nothing is happening upon clicking into it. I've also set the delegate like so:
#interface ViewController () <UISearchResultsUpdating>
Try setting definesPresentationContext to NO on the first view controller as soon as you present a new one on.
I believe that the presentation walks up the view controller hierarchy looking for the first one that defines a context and not down.
I have searched all other questions about UISearchBar and nothing seems to answer my issue. I have a navigation view at the top and a tableview with a UISearchBar. When I tap on the search bar, the tableview gets darkened, the keyboard comes up, both as they should, but the uisearchbar disappears. If I tap on the darkened out tableview, the keyboard gets dismissed, the darkeness goes away, and the UISearchBar reappears. Any idea why it is disappearing?
Here's some code which is inside a class which extends UITableViewController:
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 100, self.view.frame.size.width, 44)];
searchBar.delegate = self;
searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
searchDisplayController.delegate = self;
searchDisplayController.searchResultsDataSource = self;
searchDisplayController.searchResultsDelegate = self;
//[self.tableView insertSubview:self.searchDisplayController.searchBar aboveSubview:self.tableView];
self.tableView.tableHeaderView = searchDisplayController.searchBar;
In my .h file, I adopt these protocals: ` but I do not implement any of their methods except:
- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView
{
[tableView registerClass:[EmailCell class] forCellReuseIdentifier:mailCellIdentifier];
}
EDITED:
I purposely moved the tableview down further, so that there is whitespace between the top navigation view and the tableview, and found that the searchbar wasn't disappearing, it was moving further up on the screen when tapping the UISearchBar, occupying the whitespace that I added in. Any ideas why?
Add this method
- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller
{
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
[self.tableView insertSubview:self.searchDisplayController.searchBar aboveSubview:self.tableView];
}
}
For more detail check this link
Have a tableview with indexes. They are visible on initial load.
I also have a searchDisplayController
When I use the searchDisplayController and then cancel out of it, suddenly the indexes on the original tableview are hidden.
I never had this problem with iOS 6.
Here is my code that worked with iOS 6:
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView2 {
if (self.searchDisplayController.active)
return nil;
else
return self.indices;
}
I've tried this with no luck:
- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller {
[self.tableViewOriginal reloadSectionIndexTitles];
}
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
[self.tableViewOriginal reloadSectionIndexTitles];
}
UPDATE:
To add the tableView I use a storyboard and connect it with an IBOutlet. The searchBar and searchDisplayController are added programmatically in viewDidLoad:
self.searchBar = [[UISearchBar alloc]initWithFrame:CGRectMake(0, 0, 290, 44)];
self.searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
I then add the searchbar to a table cell if cellForRowAtIndexPath
[cell addSubview:self.searchBar];
One possible issue with your setup is that you are putting the search bar in a table view cell.
A more standard (and much simpler) approach is to make the search bar the table view's headerView.
self.tableView.headerView = self.searchBar;
Just do this once just after setting up the search display controller.