How to use the uisearchbar in objective c in iOS 10? - ios

I want to add uisearchbar in table view controller, but I search the uisearchbar tutorial in iOS 9 and try it. I can’t show the uisearchbar on the simulator of my project. It also has not the search function. If I pass the code “self.tableView.contentOffset = CGPointMake(0, CGRectGetHeight(self.searchController.searchBar.frame));”, the Xcode will show the error message. This message is “libc++abi.dylib: terminating with uncaught exception of type NSException”.
Could tell me where is wrong?
Platform: iPhone in iOS 10.3 and iPad in iOS 10.3
Xcode version:8.3.3 (8E3004b)
.h file
#import <UIKit/UIKit.h>
#interface SearchBarTableViewController : UITableViewController <UISearchControllerDelegate, UISearchBarDelegate, UISearchResultsUpdating>
#property (nonatomic, strong) UISearchController *searchController;
#property (weak, nonatomic) IBOutlet UISearchBar *searchBar;
#property(nonatomic,strong) NSMutableArray *RowArray;
#end
.m files
#pragma mark Search bar Part
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (!_searchController.searchBar.superview) {
self.tableView.tableHeaderView = self.searchController.searchBar;
}
if (!self.searchController.active && self.searchController.searchBar.text.length == 0) {
self.tableView.contentOffset = CGPointMake(0, CGRectGetHeight(self.searchController.searchBar.frame));
}
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if (self.searchController.isActive) {
self.searchController.active = NO;
}
}
#pragma mark - Getters / Setters
- (UISearchController *)searchController {
if (!_searchController) {
_searchController = [[UISearchController alloc]initWithSearchResultsController:nil];
_searchController.searchResultsUpdater = self;
_searchController.dimsBackgroundDuringPresentation = NO;
_searchController.searchBar.delegate = self;
[_searchController.searchBar sizeToFit];
}
return _searchController;
}
- (NSArray *)searchResults {
NSString *searchString = self.searchController.searchBar.text;
if (searchString.length > 0) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF CONTAINS[c] %#", searchString];
return [self.RowArray filteredArrayUsingPredicate:predicate];
}
else {
return self.RowArray;
}
return #[];
}
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (self.searchController.isActive && self.searchController.searchBar.text.length > 0) {
return self.searchResults.count;
}
else {
return self.RowArray.count;
}
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell;
NSString *cityName = #"";
cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
if (self.searchController.isActive && (![self.searchController.searchBar.text isEqualToString:#""])) {
cityName = [self.searchResults objectAtIndex:indexPath.row];
}
else {
cityName = [self.RowArray objectAtIndex:indexPath.row];
}
cell.textLabel.text = cityName;
return cell;
}
Interface image 1 about outlet setting.
UISearchbar outlet setting.
Search Display Controller outlet setting.

I have found out the answer.
I neglect the updateSearchResultsForSearchController code.
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
[self.tableView reloadData];
}

Related

Transitioning from UISearchDisplayController ==> UISearchController can't get search bar to show

I have an app that was written for iOS 7 the I need to update as UISearchDisplayController is deprecated for UISearchController.
I have went through several tutorials and tried but I cannot get this to work, however I am close.
I am following this pattern.
The problem I am running into is that the pattern I am following loads the data from a son file into an NSDict object, but my data is in an Array. No problem, I just modified the search to use a predicate (I hard coded something for now, get all records with an E in the name).
But I am getting the following error:
2017-09-12 13:01:41.538 Scoular[7644:1963822] -[employee isEqualToString:]: unrecognized selector sent to instance 0x608000105580
2017-09-12 13:01:41.604 Scoular[7644:1963822] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[employee isEqualToString:]: unrecognized selector sent to instance 0x608000105580'
In the SearchResultsTableViewController.m file, at the line
cell.textLabel.text = self.searchResults[indexPath.row];
from the m file below. I am stumped. Any help would be greatly appreciated.
#import "SearchResultsTableViewController.h"
#interface SearchResultsTableViewController ()
#property (nonatomic, strong) NSArray *array;
#end
#implementation SearchResultsTableViewController
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.searchResults count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SearchResultCell" forIndexPath:indexPath];
cell.textLabel.text = self.searchResults[indexPath.row];
return cell;
}
#end
Header File
#import UIKit;
#class EmployeeDetailViewController;
#import <CoreData/CoreData.h>
#import "EmployeeDatabase.h"
#interface EmployeeListViewController : UITableViewController
#end
Implementation File
#import "EmployeeListViewController.h"
#import "EmployeeDetailViewController.h"
#import "SearchResultsTableViewController.h"
#interface EmployeeListViewController () <UISearchResultsUpdating>
#property (nonatomic, strong) NSMutableArray *employees;
#property (nonatomic, strong) UISearchController *searchController;
#property (nonatomic, strong) NSMutableArray *searchResults;
#property (nonatomic,retain) NSMutableDictionary *sections;
#end
#implementation EmployeeListViewController
BOOL isSearching;
//Do I still need this
- (void)awakeFromNib {
if ([[UIDevice currentDevice] userInterfaceIdiom] ==
UIUserInterfaceIdiomPad) {
self.clearsSelectionOnViewWillAppear = NO;
self.preferredContentSize = CGSizeMake(320.0, 600.0);
}
[super awakeFromNib];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Get array of employees and sections
self.employees = [EmployeeDatabase getEmployees];
self.sections = [EmployeeDatabase getSections:_employees];
// 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:#"TableSearchResultsNavController"];
// 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;
// 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.tableView.tableHeaderView = self.searchController.searchBar;
// Set the back bar button
UIBarButtonItem *backButton =
[[UIBarButtonItem alloc] initWithTitle:#"Employees"
style:UIBarButtonItemStylePlain
target:nil
action:nil];
self.navigationItem.backBarButtonItem = backButton;
}
#pragma mark - Table Sections
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSInteger tmpCount;
if (isSearching) {
tmpCount = 1;
} else {
tmpCount = [[self.sections allKeys] count];
}
return tmpCount;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.employees count];
}
#pragma mark - Table View
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
}
employee *thisEmployee =
[[self.sections
valueForKey:[[[self.sections allKeys]
sortedArrayUsingSelector:
#selector(localizedCaseInsensitiveCompare:)]
objectAtIndex:indexPath.section]]
objectAtIndex:indexPath.row];
cell.textLabel.text = thisEmployee.fulNme;
return cell;
}
- (NSString *)tableView:(UITableView *)tableView
titleForHeaderInSection:(NSInteger)section {
NSString *tmpString;
//if (tableView == self.searchDisplayController.searchResultsTableView) {
//tmpString = nil;
//} else {
tmpString =
[[[self.sections allKeys]
sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:
)] objectAtIndex:section];
//}
return tmpString;
}
#pragma mark - Right side bar alphabetical index
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
NSArray *tmpTitle;
if (isSearching) {
tmpTitle = nil;
} else {
tmpTitle = [[self.sections allKeys]
sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
}
return tmpTitle;
}
#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
SearchResultsTableViewController *vc = (SearchResultsTableViewController *)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 *)employeeName
{
if (employeeName == nil) {
// If empty the search results are the same as the original data
self.searchResults = [self.employees mutableCopy];
} else {
NSArray *searchResults2 = [[NSMutableArray alloc] init];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"fulNme contains 'E'"];
searchResults2 = [self.employees filteredArrayUsingPredicate:predicate];
self.searchResults = [searchResults2 mutableCopy];
}
}
#end
In your updateFilteredContentForAirlineName function you are searching from self.employees array which probably contains employee custom class object. For that reason your self.searchResults array also containing same class object.
But in your cellForRowAtIndexPath of SearchResultsTableViewController your are doing cell.textLabel.text = self.searchResults[indexPath.row]; that means you are adding employee object as string in cell.textLabel which causing your app to crash. Instead you can try this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SearchResultCell" forIndexPath:indexPath];
employee *thisEmployee = self.searchResults[indexPath.row];
cell.textLabel.text = thisEmployee.fulNme;
return cell;
}

UISearch Controller Showing data not part of the filtered array

My Question is this. Why is the filtered table view showing rooms, after I start typing in the search bar that are not present when printing the filtered array to the console. I thought it might be that the table view cells are being reused so set the cell label text to nil to ensure the text gets reset in tableviewcellforindex: method , all to no avail. Can anyone help?
This is my Table View Controller that acts as the data source and delegate for for both my standard tableview and filtered tableview
#import <UIKit/UIKit.h>
#import "Rooms.h"
#interface RoomsTableViewController : UITableViewController
<UISearchControllerDelegate,UISearchResultsUpdating,UISearchBarDelegate,UITableViewDelegate>
#property (strong,nonatomic) NSMutableArray *roomList;
#property (strong,nonatomic) NSMutableArray *orderedRoomList;
#property (strong,nonatomic) NSMutableArray *filteredRooms;
#property (strong,nonatomic) UITableViewController *searchResultsController;
#property (strong,nonatomic) UISearchController *searchController;
#end
#import "RoomsTableViewController.h"
#interface RoomsTableViewController ()
#property BOOL searchControllerWasActive;
#property BOOL searchControllerSearchFieldWasFirstResponder;
#end
The implementation file
#implementation RoomsTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
//sort the room list into filetred by alpha numeric A10 before C1 example this will eventually be done on the server
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES comparator:^NSComparisonResult(id obj1, id obj2) {
return [(NSString *)obj1 compare:(NSString *)obj2 options:NSNumericSearch];
}];
self.orderedRoomList = (NSMutableArray*)[self.roomList sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
self.searchResultsController= [[UITableViewController alloc]initWithStyle:UITableViewStylePlain];
self.searchController = [[UISearchController alloc]initWithSearchResultsController:self.searchResultsController];
self.searchController.searchResultsUpdater=self;
[self.searchController.searchBar sizeToFit];
self.tableView.tableHeaderView=self.searchController.searchBar;
//set up the data source and delegate of this new table view to be this (roomsTableviewcontroller) view controller
self.searchResultsController.tableView.delegate=self;
self.searchResultsController.tableView.dataSource=self;
self.searchController.delegate=self;
self.searchController.dimsBackgroundDuringPresentation=NO;
self.searchController.searchBar.delegate=self;
self.definesPresentationContext=YES;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
//restore the search controllers active state
if (self.searchControllerWasActive) {
self.searchController.active = self.searchControllerWasActive;
_searchControllerWasActive=NO;
if (self.searchControllerSearchFieldWasFirstResponder) {
[self.searchController.searchBar becomeFirstResponder];
_searchControllerSearchFieldWasFirstResponder=NO;
}
}
}
-(void)searchBarBookmarkButtonClicked:(UISearchBar *)searchBar
{
[searchBar resignFirstResponder];
}
#pragma mark - UISearchControllerDelegate
- (void)willPresentSearchController:(UISearchController *)searchController {
// do something before the search controller is presented
self.navigationController.navigationBar.translucent = YES;
}
-(void)willDismissSearchController:(UISearchController *)searchController
{
self.navigationController.navigationBar.translucent = NO;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView==self.tableView) {
return [self.orderedRoomList count];
}else{
return [self.filteredRooms count];
}
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 71;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellReuseIdentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellReuseIdentifier];
if (cell==nil) {
cell= [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellReuseIdentifier];
}
Rooms *room = (tableView==self.tableView)? [self.orderedRoomList objectAtIndex:indexPath.row]: [self.filteredRooms objectAtIndex:indexPath.row];
cell.textLabel.text=nil;
NSString *labelString = [NSString stringWithFormat:#"%# %#",room.name,room.roomDescription];
cell.textLabel.text=labelString;
return cell;
}
Below is a photo of the table view in the simulator and a screen print of the check to see if the filtered array has indeed worked correctly as it has. You can see that C3 is not listed as being part of the filtered array but it still appears on screen.

How to make a view controller appear and dismiss through a modal segue from another class

I have a problem with connecting a modal segue with a view controller.
In my storyboard, I have a uicollectionview controller connecting a modal segue to a table view embedded in a uiviewcontroller.
The table view contains "filters" to filter the cells in my collection view.
So far I have been able to load the view controller when the user clicks on a button in an action sheet, which opens when the user clicks a bar button item called "more"
PICTURES
My collection view:
The UIActionSheet:
My Filters View Controller
So the problem I am having is when I click the "filters" button in the action sheet, it loads the filters view controller, and when I press the "cancel" button, I am able to close the view controller from my collection view. However, when I press the "Done" button, my collection view disappears.
My Code
MainViewController.m (Collection view)
-(void)openActionSheet {
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"What else would like to do?"
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:#"About Backpack", #"Filters", nil];
[actionSheet showInView:self.view];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
NSString *buttonTitle = [actionSheet buttonTitleAtIndex:buttonIndex];
if ([buttonTitle isEqualToString:#"Filters"]) {
[self showFilters];
}
}
#pragma mark UISearchBarDelegate
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[self applyFilters:[NSSet setWithObject:searchBar.text]];
[searchBar resignFirstResponder];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
[searchBar resignFirstResponder];
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
if (![searchText length]) {
self.dataSource = self.originalDataSource;
self.imageData = self.originalImageData;
[self.collectionView reloadData];
}
}
#pragma mark FiltersViewControllerProtocol
// "Done" button
- (void)filtersSelected:(NSSet *)filters {
[self hideFilters];
[self applyFilters:filters];
}
//"Cancel" button
- (void)filterSelectionCancelled {
[self hideFilters];
}
#pragma mark private
- (void)showFilters {
if (!self.fvc) {
self.fvc = [self.storyboard instantiateViewControllerWithIdentifier:#"filters"];
self.fvc.delegate = self;
_fvc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:_fvc animated:YES completion:nil];
}
}
-(void)hideFilters {
[_fvc dismissViewControllerAnimated:YES completion:nil];
}
- (void)applyFilters:(NSSet *)filters {
NSMutableArray *newData = [NSMutableArray array];
NSMutableArray *newItems = [NSMutableArray array];
for (NSString *s in _dataSource) {
for (NSString *filter in filters) {
if ([s rangeOfString:filter options:NSCaseInsensitiveSearch].location != NSNotFound) {
[newData addObject:s];
break;
}
}
}
for(NSInteger i = 0; i < newData.count; i++) {
NSInteger loc = [self locationOfItemGivenName:newData[i]];
backpackIcons *item = _backpackItems[loc];
[newItems addObject:item.image_url];
}
self.dataSource = newData;
self.imageData = newItems;
[self.collectionView reloadData];
}
- (NSInteger)locationOfItemGivenName:(NSString *)name {
NSInteger found = -1;
for(NSInteger i = 0; i < _backpackItems.count; i++) {
backpackIcons *item = _backpackItems[i];
if([item.name isEqualToString:name]) {
found = i;
}
}
return found;
}
FiltersViewController.h (filters table view)
#import <UIKit/UIKit.h>
#protocol FiltersViewControllerProtocol <NSObject>
- (void)filtersSelected:(NSSet *)filters;
- (void)filterSelectionCancelled;
#end
#interface FiltersViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, weak) id<FiltersViewControllerProtocol> delegate;
#end
FiltersViewController.m
#import "FiltersViewController.h"
#interface FiltersViewController ()
#property (nonatomic, strong) NSMutableSet *selectedRowObjects;
//#property (nonatomic, strong) NSArray *filters;
#end
#implementation FiltersViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.selectedRowObjects = [NSMutableSet setWithCapacity:10];
}
- (IBAction)filtersSelected:(id)sender {
[self.delegate filtersSelected:self.selectedRowObjects];
}
- (IBAction)cancelFilterSelection:(id)sender {
[self.delegate filterSelectionCancelled];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"filter" forIndexPath:indexPath];
cell.textLabel.text = [NSString stringWithFormat:#"%u", indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *obj = cell.textLabel.text;
if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
cell.accessoryType = UITableViewCellAccessoryNone;
[self.selectedRowObjects removeObject:obj];
}
else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[self.selectedRowObjects addObject:obj];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#end
Another problem I have having is that the filters table view is not loading my cell labels as well.
I appreciate all help. Thanks to anyone who can!

UISearchBar is not filtering UITableView

I'm trying to add a UISearchBar to a UITableView but the method TextDidBeginEditing is not being called. I think I am missing something simple but I can't figure it out.
Header File:
#interface TableViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate>
#property (nonatomic, strong) NSMutableArray *initialCities;
#property (nonatomic, strong) NSMutableArray *filteredCities;
#property (nonatomic, strong) UISearchBar *searchBar;
#property BOOL isFiltered;
#end
Implementation File:
#import "TableViewController.h"
#interface TableViewController ()
#end
#implementation TableViewController
#synthesize initialCities, filteredCities, isFiltered, searchBar;
- (void)loadView
{
[super loadView];
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 44.0)];
searchBar.delegate = self;
searchBar.autoresizingMask = (UIViewAutoresizingFlexibleWidth);
searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
self.tableView.tableHeaderView = searchBar;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.tableView.delegate = self;
initialCities = [[NSMutableArray alloc] initWithObjects:#"London", #"New York", #"Berlin", nil];
}
#pragma mark - UITableView DataSource Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (isFiltered == YES)
{
return filteredCities.count;
}
else
{
return initialCities.count;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
if (isFiltered == YES)
{
cell.textLabel.text = [filteredCities objectAtIndex:indexPath.row];
}
else
{
cell.textLabel.text = [initialCities objectAtIndex:indexPath.row];
}
return cell;
}
#pragma mark - UITableView Delegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
#pragma mark - UISearchBar Delegate methods
- (void)searchBar:(UISearchBar *)searchBar TextDidBeginEditing:(NSString *)searchText
{
searchBar.showsCancelButton = YES;
if (searchText.length == 0)
{
isFiltered = NO;
}
else
{
isFiltered = YES;
filteredCities = [[NSMutableArray alloc] init];
for (NSString *cityName in initialCities)
{
NSRange cityNameRange = [cityName rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (cityNameRange.location != NSNotFound)
{
[filteredCities addObject:cityName];
}
}
}
[self.tableView reloadData];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[searchBar resignFirstResponder];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
The result is that the search bar is displayed, the table view is displayed, but when I type text into the search bar the table view is not filtered. There is no crash. Any help is appreciated. Thank you.
Try this
-(void)searchBar:(UISearchBar*)searchBar textDidChange:(NSString*)searchText
{
// Your filter code
}
The method you implemented is not even present in Protocol
– searchBar:textDidChange:
– searchBar:shouldChangeTextInRange:replacementText:
– searchBarShouldBeginEditing:
– searchBarTextDidBeginEditing:
– searchBarShouldEndEditing:
– searchBarTextDidEndEditing:
(void)searchBar:(UISearchBar *)searchBar TextDidBeginEditing:(NSString *)searchText
This method is not existed in searchBar's delegate.
Use searchBarTextDidBeginEditing.
Go through this tutorial. well explained.
http://www.appcoda.com/search-bar-tutorial-ios7/
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"name contains[c] %#", searchText];
searchResults = [actualData filteredArrayUsingPredicate:resultPredicate];
}

UISearchDisplayController delegate methods not being called

I am trying to gain some knowledge on UISearchDisplayController and going through some tutorial with examples, I have the below class ready with a search bar and table view with data on it.
Header file:
#import <UIKit/UIKit.h>
#interface MyClass : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchDisplayDelegate, UISearchBarDelegate>
#property (nonatomic, strong) IBOutlet UITableView *suggestionsTableView;
#property (nonatomic, strong) IBOutlet UISearchBar *searchBar;
#end
Implementation file:
#import "MyClass.h"
#interface DVWNoteTypeSuggestionDisplayController ()
#property (nonatomic, strong) NSArray *items;
#property (nonatomic)BOOL isSearching;
#property (nonatomic, strong) NSMutableArray *filteredList;
#end
#implementation MyClass
- (id)init
{
self = [super initWithNibName:#"SuggestionDisplayController" bundle:BUNDLE];
if (self)
{
// Set the title.
self.title = #"test";
}
return self;
}
- (void)viewDidLoad
{
self.searchBar = [[UISearchBar alloc] init];
[[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
self.searchDisplayController.searchResultsDelegate = self;
self.searchDisplayController.searchResultsDataSource = self;
self.searchDisplayController.delegate = self;
self.searchBar.frame = CGRectMake(0, 0, 0, 38);
self.suggestionsTableView.tableHeaderView = self.searchBar;
self.items = [[NSArray alloc] initWithObjects:#"Item No. 1", #"Item No. 2", #"Item No. 3", #"Item No. 4", #"Item No. 5", #"Item No. 6", nil];
self.isSearching = NO;
self.filteredList = [[NSMutableArray alloc] init];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
//- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
// // Return the number of rows in the section.
// // Usually the number of items in your array (the one that holds your list)
// return [self.items count];
//}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if (self.isSearching)
{
//If the user is searching, use the list in our filteredList array.
return [self.filteredList count];
} else
{
return [self.items count];
}
}
//- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// //Where we configure the cell in each row
//
// static NSString *CellIdentifier = #"Cell";
// UITableViewCell *cell;
//
// cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// if (cell == nil) {
// cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
// }
// // Configure the cell... setting the text of our cell's label
// cell.textLabel.text = [self.items objectAtIndex:indexPath.row];
// return cell;
//}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// Configure the cell...
NSString *title;
if (self.isSearching && [self.filteredList count]) {
//If the user is searching, use the list in our filteredList array.
title = [self.filteredList objectAtIndex:indexPath.row];
} else
{
title = [self.items objectAtIndex:indexPath.row];
}
cell.textLabel.text = title;
return cell;
}
- (void)filterListForSearchText:(NSString *)searchText
{
[self.filteredList removeAllObjects]; //clears the array from all the string objects it might contain from the previous searches
for (NSString *title in self.items) {
NSRange nameRange = [title rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (nameRange.location != NSNotFound) {
[self.filteredList addObject:title];
}
}
}
#pragma mark - UISearchDisplayControllerDelegate
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
//When the user taps the search bar, this means that the controller will begin searching.
self.isSearching = YES;
}
- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
//When the user taps the Cancel Button, or anywhere aside from the view.
self.isSearching = NO;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterListForSearchText:searchString]; // The method we made in step 7
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
[self filterListForSearchText:[self.searchDisplayController.searchBar text]]; // The method we made in step 7
// Return YES to cause the search result table view to be reloaded.
return YES;
}
#end
Whenever I try to search for any items in the data set (eg: "Item No. 5") its not hitting the breakpoints on any of the delegate i.e. actually the search is not working. Please suggest what am I missing here as this is just my learning project right now.
It appears that a UISearchDisplayController created programatically in this way is prematurely zeroing the delegate, even though the view controller is retaining the UISearchDisplayController as expected.
Add the following to the end of your viewDidLoad and you'll see that the first log will be a valid object, but the second will be null.
NSLog(#"Delegate should be %#", self.searchDisplayController.delegate);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(#"Delegate is %#", self.searchDisplayController.delegate);
});
The quickest way I've found to get around this is to store your own reference to the UISearchDisplayController via a private property or ivar.
If you have to create object for search bar controller and set delegate search bar its work.
UISearchBar *searchBar = [[UISearchBar alloc] init];
[[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
self.searchDisplayController.searchResultsDelegate = self;
self.searchDisplayController.searchResultsDataSource = self;
self.searchDisplayController.delegate = self;
searchBar.frame = CGRectMake(0, 0, 0, 38);
self.tableView.tableHeaderView = searchBar;

Resources