I am trying to implement a UISearchController in a TableViewController. After i enter the text in the search bar I am getting the count in the console of how many records to display but the tableview is not getting reloaded. Please find the code for the Update Search Results Controller.
- (void)viewDidLoad {
[super viewDidLoad];
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.searchBar.delegate = self;
self.tableView.tableHeaderView = self.searchController.searchBar;
self.definesPresentationContext = YES;
_db=[[Database alloc]init];
if(_vehicles==nil){
_vehicles=[[NSMutableArray alloc]init];
}
_vehicles=[_db getTheData:nil];
NSLog(#"%lu",(unsigned long)_vehicles.count);
}
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
NSString *searchText = searchController.searchBar.text;
NSMutableArray<Vehicle*> *searchResults = [[NSMutableArray<Vehicle*> alloc]init];
for(Vehicle *v in self.vehicles){
if([v.make containsString:searchText]){
[searchResults addObject:v];
}
}
NSLog(#"%lu",searchResults.count);
VehicleTableViewController *tableController = (VehicleTableViewController *)self.searchController.searchResultsController;
tableController.vehicles = searchResults;
[tableController.tableView reloadData];
}
VehicleTableViewController *tableController = (VehicleTableViewController *)self.searchController.searchResultsController;
This line is wrong I think. searchResultsController is not tableviewctrler. You cannot force it to be one. You already have tableView reference so use that.
[self.tableView reloadData];
Make sure you replace the Table datasource with the searchresult before reloading the table.
[dataSourceArr removeAllObjects];
[dataSourceArr = [NSMutableArray arrayWithArray: searchResults];
Related
Creating a search view, this is the code that i did for the main search view.
What happens is if i dont search/filter, the uisearchbar gets dismissed when segueing. but if i search/filter then the uisearchbar stays on the nav bar when seguing.
- (void)viewDidLoad {
[super viewDidLoad];
// There's no transition in our storyboard to our search results tableview or navigation controller
// so we'll have to grab it using the instantiateViewControllerWithIdentifier: method
UINavigationController *searchResultsController = [[self storyboard] instantiateViewControllerWithIdentifier:#"CompanySearchResultsNavigationController"];
// Our instance of UISearchController will use searchResults
self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
// The searchcontroller's searchResultsUpdater property will contain our tableView.
self.searchController.searchResultsUpdater = self;
self.searchController.hidesNavigationBarDuringPresentation = NO;
// The searchBar contained in XCode's storyboard is a leftover from UISearchDisplayController.
// Don't use this. Instead, we'll create the searchBar programatically.
self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, self.searchController.searchBar.frame.origin.y, self.searchController.searchBar.frame.size.width, 44.0);
self.navigationItem.titleView = self.searchController.searchBar;
self.definesPresentationContext = YES;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.objects count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
CompanySearchTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"searchCell" forIndexPath:indexPath];
cell.productImageView.file = (PFFile *)object[#"profileImage"];
cell.productImageView.layer.cornerRadius = cell.productImageView.frame.size.width / 2;
cell.productImageView.clipsToBounds = YES;
[cell.productImageView loadInBackground];
cell.companyNameLabel.text = object[#"username"];
return cell;
}
#pragma mark - UISearchControllerDelegate & UISearchResultsDelegate
// Called when the search bar becomes first responder
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
// Set searchString equal to what's typed into the searchbar
NSString *searchString = self.searchController.searchBar.text;
[self updateFilteredContentForAirlineName:searchString];
// If searchResultsController
if (self.searchController.searchResultsController) {
UINavigationController *navController = (UINavigationController *)self.searchController.searchResultsController;
// Present SearchResultsTableViewController as the topViewController
CompanySearchResultsTableViewController *vc = (CompanySearchResultsTableViewController *)navController.topViewController;
// Update searchResults
vc.searchResults = self.searchResults;
// And reload the tableView with the new data
[vc.tableView reloadData];
}
}
// Update self.searchResults based on searchString, which is the argument in passed to this method
- (void)updateFilteredContentForAirlineName:(NSString *)companyName
{
if (companyName == nil) {
// If empty the search results are the same as the original data
self.searchResults = [self.objects mutableCopy];
} else {
NSMutableArray *searchResults = [[NSMutableArray alloc] init];
// Else if the airline's name is
for (PFObject *company in self.objects) {
if ([company[#"username"] containsString:companyName]) {
// NSString *str = [NSString stringWithFormat:#"%#", company[#"username"]];
// [searchResults addObject:str];
PFObject *searchedObject = company;
[searchResults addObject:searchedObject];
NSLog(#"Searched: %#",searchedObject[#"username"]);
}
self.searchResults = searchResults;
}
}
}
In your AirlineTableViewController, override [UIViewController prepareForSegue]:
- (void)prepareForSegue:(UIStoryboardSegue *)segue
sender:(id)sender {
[self.searchController setActive:NO];
}
I am new to iOS programming.
I have to implement a location search based on the third party map API, but I think I have messed up multiple view controllers.
Scenario:
I have a mapviewController for displaying the mapview. And I have a searchController for searchbar. There is a resultviewController property in searchController for display the search suggestions.
I have tried to add search VC as child VC to map VC, but once I click to the search bar it returns "Application tried to present modally an active controller".
So then I remove search VC from map VC & the search bar is not activated.
Therefore I want to ask how to handle these VCs, and avoid the case that map view covers the search bar and suggestion lists.
Thank you so much.
UPDATE:
I'm building a search bar in code. My aim is to build the following style in iOS.
like this http://i1.tietuku.com/cd4efa23d97af75ft.jpg
I pushed the map viewController to the navigation controller from menu.
[self.navigationController pushViewController:mapviewController animated:YES];
And trying to add a searchController to it.
- (void)viewDidLoad {
[super viewDidLoad];
_resultsTableController = [[UITableViewController alloc] init];
_searchController = [[UISearchController alloc] initWithSearchResultsController:self.resultsTableController];
_searchController.searchResultsUpdater = self;
[_searchController.searchBar sizeToFit];
_resultsTableController.tableView.tableHeaderView = _searchController.searchBar;
self.searchController.searchBar.delegate = self;
_resultsTableController.tableView.delegate = self;
_searchController.delegate = self;
_searchController.dimsBackgroundDuringPresentation = NO;
_searchController.searchBar.delegate = self;
mapView = [[BMKMapView alloc]initWithFrame:CGRectMake(0, kHeight(100), kScreen_Width , kScreen_Height-kHeight(100))];
[self addChildViewController:_searchController];
[self.view addSubview: _searchController.view];
[self.view addSubview:mapView];
}
for UISearchController you no need to add it as child view controller and and instant of using UITableViewController uses UITableView it make easy for you and
here below is code that is .m file
free to run that code and without uses storyboard.
#interface ViewController ()
{
UITableView *tableview;
UISearchController *searchcontroller;
NSMutableArray *array;}
#end
#implementation ViewController
(void)viewDidLoad
{
[super viewDidLoad];
array = [[NSMutableArray alloc]initWithObjects:#"one",#"two",#"three",#"four", nil];
tableview = [[UITableView alloc]initWithFrame:CGRectMake(0, 50, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame)/2)];
[self.view addSubview:tableview];
tableview.dataSource = self;
tableview.delegate =self;
searchcontroller = [[UISearchController alloc]initWithSearchResultsController:nil]; // Create Reference of searchController
searchcontroller.searchResultsUpdater = self;
searchcontroller.searchBar.backgroundColor = [UIColor redColor];
searchcontroller.searchBar.barStyle = UIBarStyleBlack;
searchcontroller.searchBar.barTintColor = [UIColor whiteColor];
searchcontroller.dimsBackgroundDuringPresentation = false;
[searchcontroller.searchBar sizeToFit];
tableview.tableHeaderView = searchcontroller.searchBar;
MKMapView *mapview = [[MKMapView alloc]initWithFrame:CGRectMake(0, CGRectGetMaxY(tableview.frame), CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame)/2)];
[self.view addSubview:mapview];
}
(void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController;
{
NSLog(#"update ");
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
// Default is 1 if not implemented
{
return 1;
}
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return array.count;
}
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
}
cell.textLabel.text = array[indexPath.row];
return cell;
}
According to me you should use only one view controller which has a map on it. Over the map you can simply add custom search view and on typing/ taping search you can show search results using UITableview with some dropping animation keeping some max frame fixed, And finally on taping any result remove this UITableView and show location of map. If time permits I will create a sample for you, cant give assurance but will try. Mean while you can also go through Maps reference may be helpful
I created a search bar at the header view of a table:
self.searchResults = [NSMutableArray arrayWithCapacity:[self.list count]];
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.hidesNavigationBarDuringPresentation = NO;
self.searchController.searchBar.barTintColor = [UIColor clearColor];
self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, self.searchController.searchBar.frame.origin.y, self.searchController.searchBar.frame.size.width, 44.0);
[[UIBarButtonItem appearanceWhenContainedIn: [UISearchBar class], nil] setTintColor:[UIColor whiteColor]];
[self.searchController.searchBar becomeFirstResponder];
And when tap a certain row in the tableview, a new view controller will be pushed.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSLog(#"HEY ROW %ld", indexPath.row+1);
ZLContainerViewController *controller = [[ZLContainerViewController alloc]init]; // a container for UIPage
[self.navigationController pushViewController:controller animated:YES];
}
However, after pushing the new view controller, the search bar is still there. How can I solve this problem?
Any suggestion is much appreciated!
Use the below code in viewDidLoad.
Swift:
self.definesPresentationContext = true
Objective-C:
self.definesPresentationContext = YES;
This solved the problem for me.
One of these two UISearchBarDelegate delegate methods should fix your problem
- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar {
return YES;
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
[self.searchBar resignFirstResponder];
}
I've implemented UISearchControl (iOS8 version which is slightly different then previous ones). It seems to be firing correctly when I type stuff in according to the NSLog statement seen below, only issue is it the UITableView actually never gets updated, and I added a NSLog to the } else { part of the numberOfRowsInSection to confirm that it's not called like so:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.tableView) {
return self.objects.count;
} else {
// NOT BEING FIRED WHEN STUFF IS TYPED IN SEARCH BAR?
NSLog(#"Search Results Returned in TableView");
return self.searchResults.count;
}
}
Although these methods are firing fine...and updating the searchResults array correctly according to the NSLog added in the updateFilter method:
#pragma mark - UISearchResultsUpdating
-(void)updateSearchResultsForSearchController:(UISearchController *)searchController {
NSString *searchString = [self.searchController.searchBar text];
[self updateFilteredContentForSaleName:searchString];
// ASSUMING THIS IS WHAT CAUSES TABLEVIEW TO REFRESH, BUT ISNT REFRESHING IT WITH NEW ARRAY?
[((UITableViewController *)self.searchController.searchResultsController).tableView reloadData];
}
#pragma mark - Content Filtering
- (void)updateFilteredContentForSaleName:(NSString *)saleName {
[self.searchResults removeAllObjects];
for (PFObject *sale in self.objects)
{
NSString *saleTitle = [sale objectForKey:#"name"];
if ([[saleTitle lowercaseString] hasPrefix:[saleName lowercaseString]])
{
[self.searchResults addObject:sale];
}
}
// THIS LOG SHOWS SEARCH RESULTS CORRECTLY HOW THEY SHOULD BE, JUST NO UPDATE TO UITABLEVIEW
NSLog(#"%#", self.searchResults);
}
But simply no update to the tableview...
Any idea why this is? Am I calling the refresh wrong here?:
[((UITableViewController *)self.searchController.searchResultsController).tableView reloadData];
I've tried PFQueryTableViewController * too since that's essentially what I'm using for actual view controller, but no luck.
EDIT
Here is the code used to create the UISearchControl
#interface LocalSalesViewController () <UISearchResultsUpdating>
#property (nonatomic, strong) UISearchController *searchController;
#property (nonatomic, strong) NSMutableArray *searchResults; // Filtered search results
#end
#implementation LocalSalesViewController
- (id)initWithCoder:(NSCoder *)aCoder {
self = [super initWithCoder:aCoder];
if (self) {
self.parseClassName = #"Sales";
self.pullToRefreshEnabled = YES;
self.paginationEnabled = YES;
self.objectsPerPage = 25;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.searchResults = [NSMutableArray array];
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, self.searchController.searchBar.frame.origin.y, self.searchController.searchBar.frame.size.width, 44.0);
self.tableView.tableHeaderView = self.searchController.searchBar;
self.definesPresentationContext = YES;
}
I have a UITableViewController and I want a UISearchBar on the top so I use
viewForHeaderInSection: delegate method because when I scroll I don't want to hide the UISearchBar. The problem is (only iOS7) that when I press cancel button the UISearchBar disappears.
here is some code:
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:UITableViewStylePlain];
if (self) {
// Custom initialization
self.filteredListContent = [[NSMutableArray alloc] init];
mySearchBar = [[UISearchBar alloc] init];
mySearchBar.delegate = self;
[mySearchBar setAutocapitalizationType:UITextAutocapitalizationTypeNone];
[mySearchBar sizeToFit];
searchDisplayController = [[UISearchDisplayController alloc]initWithSearchBar:mySearchBar contentsController:self];
[searchDisplayController setDelegate:self];
[self setSearchDisplayController:searchDisplayController];
[searchDisplayController setSearchResultsDataSource:self];
self.tableView.scrollEnabled = YES;
}
return self;
}
Then I return mySearchBar on viewForHeaderInSection: delegate method.
What's wrong with that?