26

I have an app which displays quite a lot of data in a UITableView. I already added the UISearchBar and UISearchDisplayController in Interface Builder to the UITableView. But I do not know how to use it. If someone could provide a quick solution to this, I would be grateful. I just require it to work as you type to find matches of the search query in the UITableView cells (or from an array).

UPDATE 1: Here's the code from thenumberOfRowsInSection method:

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section  
{  
if (isSearching) {  
        return [searchResults count];  
    }  
    else {  
        if (section == 0) {  
            return 1;  
        }  
        else if (section == 1) {  
            return [basicQuantities count];  
        }  
        else if (section == 2) {  
            return [physicalQuantities count];  
        }  
    }  

    return nil;  
}
Youssef Moawad
  • 2,846
  • 5
  • 28
  • 50

2 Answers2

84
  • First add the UISearchDisplayController to your table view
  • Then set its delegate.
  • Implement the following methods.

Demo Project

In your .h File

    @interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {

    NSMutableArray *contentList;
    NSMutableArray *filteredContentList;
    BOOL isSearching;
}
@property (strong, nonatomic) IBOutlet UITableView *tblContentList;
@property (strong, nonatomic) IBOutlet UISearchBar *searchBar;
@property (strong, nonatomic) IBOutlet UISearchDisplayController *searchBarController;

In your .m File

Filling the sample data (Optional Only For Demo Purpose)

- (void)viewDidLoad {
    [super viewDidLoad];
    contentList = [[NSMutableArray alloc] initWithObjects:@"iPhone", @"iPod", @"iPod touch", @"iMac", @"Mac Pro", @"iBook",@"MacBook", @"MacBook Pro", @"PowerBook", nil];
    filteredContentList = [[NSMutableArray alloc] init];
}

Now implement the Table View Delegate and Datasource

- (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.
    if (isSearching) {
        return [filteredContentList count];
    }
    else {
        return [contentList 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];
    }

    // Configure the cell...
    if (isSearching) {
        cell.textLabel.text = [filteredContentList objectAtIndex:indexPath.row];
    }
    else {
        cell.textLabel.text = [contentList objectAtIndex:indexPath.row];
    }
    return cell;

}

Search Function Responsible For Searching

- (void)searchTableList {
    NSString *searchString = searchBar.text;

    for (NSString *tempStr in contentList) {
        NSComparisonResult result = [tempStr compare:searchString options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchString length])];
        if (result == NSOrderedSame) {
            [filteredContentList addObject:tempStr];
        }
    }
}

Search Bar Implementation

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
    isSearching = YES;
}

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
    NSLog(@"Text change - %d",isSearching);

    //Remove all objects first.
    [filteredContentList removeAllObjects];

    if([searchText length] != 0) {
        isSearching = YES;
        [self searchTableList];
    }
    else {
        isSearching = NO;
    }
    // [self.tblContentList reloadData];
}

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
    NSLog(@"Cancel clicked");
}

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    NSLog(@"Search Clicked");
    [self searchTableList];
}
icodebuster
  • 8,890
  • 7
  • 62
  • 65
  • actually I am still trying to implement this. It is giving me an exception at the `numberOfRowsInSection` method. – Youssef Moawad Sep 11 '13 at 07:02
  • @YoussefSami what error are you getting...? Just check did you alloc the searchResultArray. – icodebuster Sep 11 '13 at 08:10
  • `Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITableView tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x9044600'` I just did `alloc init`, though it still sends this. – Youssef Moawad Sep 11 '13 at 08:17
  • 1
    Yes the exception gets sent once I tap the UISearchBar. – Youssef Moawad Sep 11 '13 at 11:11
  • @YoussefSami Please check the updated answer...Also Check the Demo Project. – icodebuster Sep 11 '13 at 11:41
  • I implemented the code in the updated answer. It still sends the same exception. Before the exception was sent when I start typing in the search bar. Now (started using Xcode 5 to develop for iOS 7) it sends it once I tap the search bar. It is the same `Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITableView tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x9044600'` though. Thanks for your help so far. – Youssef Moawad Sep 11 '13 at 12:26
  • @YoussefSami This error is with respect to `-[UITableView tableView:numberOfRowsInSection:]` Check what value are you pasing...Even try the demo project attached. – icodebuster Sep 11 '13 at 12:40
  • I just updated the question with the code from the `numberOfRowsAtIndex` Method. – Youssef Moawad Sep 11 '13 at 13:12
  • I am past the previous exception (the `numberOfSectionsInTableView` method was always returning 3 without checking for `isSearching`) but now it sends an out of bounds array exception. While debugging both my project and the demo one, I noticed that in mine in calls `cellForRowAtIndexPath` once I tap the UISearchBar while in yours it calls it when you start editing. – Youssef Moawad Sep 11 '13 at 15:36
  • @YoussefSami Just log the count of all the arrays. – icodebuster Sep 11 '13 at 15:45
  • @YoussefSami Check your tableview datasource. – icodebuster Sep 12 '13 at 09:42
  • 1
    @icodebuster Thanks for example, I want to notice you about a bug, you should implement `searchBarTextDidEndEditing` and set `isSearching` as NO. Otherwise it throws exception because data loaded from wrong array in the `cellForRowAtIndexPath` when you scroll downwards. – Ömer Faruk Almalı Jan 11 '14 at 12:43
  • There's a bug – you should only reload the table in the if clause. If you do it outside, your tblContentList might already be destroyed if another view controller gets presented. Hope this helps anyone who was trying to debug a crash! – Sidwyn Koh Mar 04 '14 at 03:59
  • @SidwynKoh Thanks for pointing it out..there is no need for reload actually :) – icodebuster Mar 04 '14 at 04:16
  • 7
    Instead of doing a `if(isSearching)` check, I check if the table view passed in is equal to the `UISearchDisplayController`, I think it is a much more secure check. `if(self.searchController.searchResultsTableView == tableView)` – SirRupertIII May 02 '14 at 15:13
  • @rptwsthi Thanks for the heads up, Demo link now fixed. If you find the answer useful please up-vote it :) – icodebuster May 04 '14 at 11:29
  • @icodebuster demo link is not working.. please update with link – ChenSmile Jul 04 '15 at 05:49
  • @icodebuster ok i got ur point and now where should i call web service request in your code.. – ChenSmile Jul 04 '15 at 08:03
  • Could you be more specific about your requirement. Web service call and search bar are 2 different things. You can create a separate function and call the web service and when you get the data you need to set the data to tableview. – icodebuster Jul 04 '15 at 08:07
  • @icodebuster i want to make a service call request when user type something in search bar and . the request will be made and result will be displayed in table – ChenSmile Jul 04 '15 at 08:12
  • Thanks a lot for your demo project!!! After following lots of link finally yours one is working for me. Thank you so much.. – iGatiTech Jul 24 '15 at 11:29
  • 2
    @icodebuster uisearchdisplaycontroller is depreciated in ios9. please update ur demo code with new search – ChenSmile Sep 30 '15 at 05:48
6

Here is a good tutorial how to do that. It's too much to just write about it :)

http://www.appcoda.com/how-to-add-search-bar-uitableview/

Grzegorz Krukowski
  • 18,081
  • 5
  • 50
  • 71