UISearchController cannot access tableview - ios

I have a searchController on my screen
My problem is that when I type in to my tableview to tap a cell. the search controller is above the tableview and I cannot select the cell.,
Init method
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
- (void)updateSearchResultsForSearchController:(UISearchController *)aSearchController {
NSLog(#"updateSearchResultsForSearchController");
NSString *searchString = aSearchController.searchBar.text;
NSLog(#"searchString=%#", searchString);
// [self.moviesTableView setContentOffset:CGPointMake(0, 0)];
// Check if the user cancelled or deleted the search term so we can display the full list instead.
if (![searchString isEqualToString:#""]) {
[self.filteredMovies removeAllObjects];
for (FLMovie *movie in self.movies) {
if ([searchString isEqualToString:#""] || [movie.title localizedCaseInsensitiveContainsString:searchString] == YES) {
[self.filteredMovies addObject:movie];
}
}
self.displayedItems = self.filteredMovies;
}
else {
self.displayedItems = self.movies;
}
[self.moviesTableView reloadData];
}
}

I fixed it by removing the dimming background during presentation.
self.searchController.dimsBackgroundDuringPresentation = NO;

Related

UISearchController Not working

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];

How to dismiss UISearchBar once segued

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];
}

Present UISearchController after button tapped

I am looking for a way how to present a search view with search bar after button is tapped. Am I suppose to create a new UIView with search bar and then after button is tapped segue to that UIView? Or is there a better option?
You can imagine that as searching in Youtube app but you would see search results while typing.
EDIT:
So now I managed to present search bar after button is tapped but it is not displaying correctly. Problem is when the search bar is moved lower it is being cut from down:
My code:
implementation ViewController {
NSInteger listNo;
DataClass *dataClass;
UITableViewController *searchResultsController;
}
- (void)viewDidLoad {
[super viewDidLoad];
dataClass = [DataClass getInstance];
self.navigationController.navigationBarHidden = YES;
// Prepare Search Controller and Result Controller
searchResultsController = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain];
searchResultsController.tableView.dataSource = self;
searchResultsController.tableView.delegate = self;
self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
self.searchController.searchResultsUpdater = self;
self.searchController.delegate = self;
self.searchController.searchBar.delegate = self;
self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, self.searchController.searchBar.frame.origin.y + 5, self.searchController.searchBar.frame.size.width, 44.0);
[self.searchController.searchBar sizeToFit];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 5;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 3;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
cell.textLabel.text = #"Ahoj";
return cell;
}
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
}
- (void)didDismissSearchController:(UISearchController *)searchController {
}
// Load data to next view
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showTable"]) {
AdditivesTableViewController *atvc = (AdditivesTableViewController *)segue.destinationViewController;
switch (listNo) {
case 0:
atvc.additivesList = [[NSMutableArray alloc] initWithArray:(NSArray *)dataClass.nonDangerousAdditives];
break;
case 1:
atvc.additivesList = [[NSMutableArray alloc] initWithArray:(NSArray *)dataClass.mediumDangerousAdditives];
break;
case 2:
atvc.additivesList = [[NSMutableArray alloc] initWithArray:(NSArray *)dataClass.dangerousAdditives];
break;
case 3:
atvc.additivesList = [[NSMutableArray alloc] initWithArray:(NSArray *)dataClass.highDangerousAdditives];
break;
default:
atvc.additivesList = [[NSMutableArray alloc] initWithArray:(NSArray *)dataClass.allAdditives];
break;
}
}
}
#pragma mark - IBActions
- (IBAction)nonDangList:(id)sender {
listNo = 0;
[self performSegueWithIdentifier:#"showTable" sender:self];
}
- (IBAction)medDangList:(id)sender {
listNo = 1;
[self performSegueWithIdentifier:#"showTable" sender:self];
}
- (IBAction)dangList:(id)sender {
listNo = 2;
[self performSegueWithIdentifier:#"showTable" sender:self];
}
- (IBAction)highDangList:(id)sender {
listNo = 3;
[self performSegueWithIdentifier:#"showTable" sender:self];
}
- (IBAction)searchAdditive:(id)sender {
[self.view addSubview:self.searchController.searchBar];
[self.searchController setActive:YES];
[self.searchController.searchBar becomeFirstResponder];
}
#end

UISearchControl delegate fired but no objects showing up in Tableview

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;
}

App crash while editing a UISearchBar and dismissing UITableViewController

I am seeing a bug where my app crashes if I click the back button in a navigation controller while editing a UISearchBar embedded as the titleView of the UINavigationBar. The main VC is a UITableViewController that is pushed onto the view stack using [parentView.navigationController pushViewController:myTableView animated:YES];
Here is the code I use to create the UISearchBar in my viewDidLoad:
UISearchBar *customSearch = [[UISearchBar alloc] initWithFrame:
CGRectMake(0,0, 320, 44)];
customSearch.delegate = self;
customSearch.placeholder = #"Some placeholder text";
self.navigationItem.titleView = customSearch;
These are my delegate implementations for the UISearchBar delegate - handle search just updates the array backing the tableView and calls [self.tableview reloadData]:
- (void) searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
searchBar.showsCancelButton = YES;
}
- (void) searchBarTextDidEndEditing:(UISearchBar *)searchBar {
searchBar.showsCancelButton = NO;
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[self handleSearch:searchBar];
[searchBar resignFirstResponder];
}
- (void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
[self handleSearch:searchBar];
}
- (void)handleSearch:(UISearchBar *)searchBar {
[self updateFilteredData:searchBar.text];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *) searchBar {
searchBar.text = #"";
[self handleSearch:searchBar];
[searchBar resignFirstResponder];
}
I don't get any information from the crash - just a sigkill. If I'm not editing the UISearchBar it works fine. I've tried resigning the first responder and it still crashes.
Update - adding filtered data
- (void) updateFilteredData: (NSString *) nameFilter {
if (nameFilter.length) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(first_name CONTAINS[cd] %#) OR (last_name CONTAINS[cd] %#)", nameFilter, nameFilter];
self.filteredData = [self.data filteredArrayUsingPredicate:predicate];
} else {
self.filteredData = self.data;
}
[self.tableView reloadData];
}
I've tried all of the following + all of them together in viewWillDisappear. They all run successfully and the searchBar reference is to a valid UISearchBar.
-(void)viewWillDisappear:(BOOL)animated {
UISearchBar *mySearchBar = (UISearchBar *)self.navigationItem.titleView;
[mySearchBar resignFirstResponder];
mySearchBar.delegate = nil;
self.navigationItem.titleView = nil;
for (UIView *view in [mySearchBar subviews] ) {
[view removeFromSuperview];
}
[mySearchBar removeFromSuperview];
[super viewWillDisappear:animated];
}
It may not be a search bar thing, I just see the crash consistently when I'm editing the search bar - It could be something with the view hiding the keyboard and trying to redraw the cells below at the same time the TableView is being deconstructed.

Resources