iOS

How To Add Search Bar in Table View


Update: If you’re developing on Xcode 5 and iOS 7, check out the updated tutorial here.

One common questions I got about UITableView is how to implement a search bar for data searching. This tutorial will show how to add a search bar to the Tab Bar project. With the search bar, the app lets users search through the recipe list by specifying a search term.

Well, it’s not difficult to add a search bar but it takes a little bit of extra work. We’ll continue to work on the Xcode project we developed in the previous tutorial. If you haven’t gone through the tutorial, take some time to check it out or you can download the project here.

iOS App Search Bar

Understanding Search Display Controller

You can use search display controller (i.e. UISearchDisplayController class) to manage search in your app. A search display controller manages display of a search bar and a table view that displays the results of a search of data.

When a user starts a search, the search display controller will superimpose the search interface over the original view and display the search results. Interestingly, the results are displayed in a table view that’s created by the search display controller.

Search Results Table View vs Table View

Search Results Table View vs Table View

Like other view controllers, you can either programmatically create the search display controller or simply add it into your app using Storyboard. In this tutorial, we’ll use the later approach.

Adding a Search Display Controller in Storyboard

In Storyboard, drag and add the “Search Bar and Search Display Controller” right below the navigation bar of Recipe Book View Controller. If you’ve done correctly, you should have a screen similar to the below:

Adding Search Display Controller

Adding Search Display Controller

Before proceeding, try to run the app and see how it looks. Without implementing any new code, you already have a search bar. Tapping the search bar will bring you to the search interface. Yet, the search won’t give you the correct search result.

Search Bar in Table View App

Search Bar in Table View App But Not Working Yet

We Did Nothing but Why Search Results Show All Recipes?

As mentioned earlier, the search results are displayed in a table view created by the search display controller. When developing the table view app, we implement the UITableViewDataSource protocol to tell Table View how many rows to display and the data in each row.

Like UITableView, the table view created by the search display controller adopts the same approach. By referring to the official documentation of UISearchDisplayController, here are the available delegates that let you interact with the search result and search bar:

The search results table view’s data source.
This object is responsible for providing the data for the results table.

The search results table view’s delegate.
This object is responsible for, amongst other things, responding to the user’s selection of an item in the results table.

The search display controller’s delegate.
The delegate conforms to the UISearchDisplayDelegate protocol. It is notified of events such as when the search starts or ends, and when the search interface is displayed or hidden. As a convenience, it may also be told about changes to the search string or search scope, so that the results table view can be reloaded.

The search bar’s delegate.
This object is responsible for responding to changes in the search criteria.

Typically, the original view controller is used as the source object for the search results data source and delegate. You do not need to manually link up the data source and delegate with the view controller. As you insert the search bar into the view of Recipe Book View Controller, the appropriate connections to the search display controller are automatically configured. You can press the “control” key and click on the “Search Display Controller” to reveal the connections.

Search Display Controller Connections

Search Display Controller Connections

Both table views (i.e. the table view in Recipe Book View Controller and the search result table view) shares the same view controller to handle data population. If you refer to the code, these are the two methods being invoked when displaying table data:

This explains why the search results show a full list of recipes regardless of your search term.

Implementing Search Filter

Obviously, to make the search works, there are a couple of things we have to implement/change:

  1. Implement methods to filter the recipe names and return the correct search results
  2. Change the data source methods to differentiate the table views. If the tableView being passed is the table view of Recipe Book View Controller, we show all recipes. On the other hand, if it’s a search result table view, only the search results are displayed.

First, we’ll show you how to implement the filter. Here we have an array to store all recipes. We create another array to store the search results. Let’s name it as “searchResults”.

Next, add a new method to handle the search filtering. Filtering is one of the common tasks in iOS app. The straightforward way to filter the list of recipes is to loop through all the names and filter the result with the if-statement. There is nothing wrong with such implementation. But iOS SDK offers a better way known as Predicate to handle search queries. By using NSPredicate (which is an object representation of a predicate), you write less code. With just two lines of code, it searches through all recipes and returns the matched results.

Basically, a predicate is an expression that returns a Boolean value (true or false). You specify the search criteria in the format of NSPredicate and use it to filter data in the array. NSArray provides filteredArrayUsingPredicate: method which returns a new array containing objects that match the specified predicate. The SELF keyword in the predicate “SELF contains[cd] %@” refers to the objects being evaluated (i.e. recipes). The operator “[cd]” means the comparison is case- and diacritic-insensitive.

If you want to learn more about Predicate, check out Apple’s official documentation or the tutorial written by Peter Friese.

Implementing Search Display Controller Delegate

Now we’ve created a method to handle the data filtering. But when should it be called? Apparently the filterContentForSearchText: method is invoked when user keys in the search term. The UISearchDisplayController class comes with a shouldReloadTableForSearchString: method which is automatically called every time the search string changes. So add the following method in the RecipeBookViewController.m:

Display Search Results in searchResultsTableView

As explained earlier, we have to change the data source methods as to differentiate the table views (i.e. the table view in Recipe Book View Controller and the search result table view). It’s pretty easy to differentiate the table view. We simply compare the tableView object against the “searchResultsTableView” of the “searchDisplayController”. If the comparison is positive, we display the search results instead of all recipes. Here are the changes of the two methods:

Test the App Again

Once you complete the above changes, test your app again. Now the search bar should work properly!

Search Bar Complete

Handling Row Selection in Search Results

Despite the search works, it doesn’t respond to your row selection. We want to make it work like the recipe table view. When user taps on any of the search results, it’ll transit to the detail view displaying the name of selected recipe.

Earlier, we use Segue to link up the recipe table cell and detail view. (If you forgot how it was done, revisit the Segue tutorial to see how it works.)

Obviously, we have to create another Segue in Storyboard to define the transition between the search result and detail view. The problem is we can’t do that. The search result table view is a private variable of search display controller. It’s impossible to handle the row selection of the search results using Storyboard.

The search display table view, however, lets you interact with the user’s selection of the results table by using a delegate. When the user selects a row, the didSelectRowAtIndexPath: method will be called. Therefore, what we have to do is to implement the method:

We simply invoke the performSegueWithIdentifier: method to manually trigger the “showRecipeDetail” segue. Before proceeding, try to run the app again. When you select any of the search results, the app shows the detail view with a recipe name. But the name is not always correct.

Referring to the prepareForSegue: method, we use the “indexPathForSelectedRow” method to retrieve the indexPath of the selected row. As mentioned earlier, the search results are displayed in a separate table view. But in our original prepareForSegue: method, we always retrieve the selected row from the table view of Recipe Book View Controller. That’s why we got the wrong recipe name in detail view. To make the selection of search results properly, we have to tweak the prepareForSegue: method:

We first determine if the user is using search. When searching, we retrieve the indexPath from searchResultsTableView, which is the table view for search results. Otherwise, we just get the indexPath from the table view of Recipe Book View Controller.

That’s it. Run the app again and the search selection should work as expected.

Search Results Selected

Tell Us What You Think

Hope you find this tutorial useful. If you like the tutorial and have any ideas about future tutorial, leave us comment and tell us what you think. We need your support to keep publishing free tutorials 🙂

Update: You can now download the full source code for your reference.

iOS
Working with UITableView in Xcode 5 Using Storyboard
iOS
Understanding Self Sizing Cells and Dynamic Type in iOS 8
iOS
Working with SQLite Databases in iOS with FMDB Library
  • Keane Kwa

    Keane KwaKeane Kwa

    Author Reply

    Thanks, great tutorial.


  • Nazmul

    NazmulNazmul

    Author Reply

    Great tutorial. I shall be grateful if you could make one tutorial for how to consume web service. Thanks!


    • Simon Ng

      Simon NgSimon Ng

      Author Reply

      Thanks for your suggestion. I’ll put it in my to-do list. 🙂


    • Simon Ng

      Simon NgSimon Ng

      Author Reply

      Thanks for your suggestion. I’ll put it in my to-do list. 🙂


      • Anonymous

        AnonymousAnonymous

        Author Reply

        Could you make a tutorial where you can search the valueForKey:@”info” (for example) of every cell in your table view… In other words, can you make it so you can search a cell’s array instead of its title? Thanks.


  • Jake

    JakeJake

    Author Reply

    great tutorial this was really helpful


  • halunke

    halunkehalunke

    Author Reply

    Great tutorial as always! I would like to see something about further DetailView customizations (like images, lists, geo-location, weather or so) all in relation to what list-item you selected.
    Or something about CoreData 🙂


  • Fredrik

    FredrikFredrik

    Author Reply

    Really good tutorial! Thanks!


  • Bubumuk

    BubumukBubumuk

    Author Reply

    Great tutorial. Thanks!

    I’d like to see something about CoreData and WebServices too like @7116a3171a2725aed8c83acd95a411cb:disqus and @fd7aca0e82906fbbf517913ee5a91232:disqus said.


    • Simon Ng

      Simon NgSimon Ng

      Author Reply

      Thanks for the suggestions. I’ll definitely cover both topics in the advanced tutorials.


    • Simon Ng

      Simon NgSimon Ng

      Author Reply

      Thanks for the suggestions. I’ll definitely cover both topics in the advanced tutorials.


  • Divz

    DivzDivz

    Author Reply

    Great tutorial.This was really helpful.Thanks..


  • Bubumuk

    BubumukBubumuk

    Author Reply

    Hey, what do you think about a tutorial about pagination of the tableView?
    Thanks.


  • James

    JamesJames

    Author Reply

    Excellent tutorial. I got a challenge for you. Instead of displaying the name in the detail view display a description and image. So like an image of egg benedict and a description of it;)


    • Simon Ng

      Simon NgSimon Ng

      Author Reply

      Later I’ll definitely cover this part. But it shouldn’t be difficult to implement. I suggest to try it out yourself. In the detail view, add an image view and a label for the description. Then declare two instance variables in the detail view controller and link the variables with the UI elements. You can then pass the description and image to the detail view via segue. That’s very similar to the things we’ve done before.


      • James

        JamesJames

        Author Reply

        Thanks for the reply I will give it a shot:)


      • nancy

        nancynancy

        Author Reply

        please i wan a your urgent help:
        i wana add search bar that applied for all the application for example if i divide the recipe into two menu such as chicken and desserts how do i execute the search through these two table views….
        in other words how to determine the scope of my search bar…
        thank you sooo much in advance..


  • dar

    dardar

    Author Reply

    Awsome man. Been doing all your tutorials, never done xCode before. Really clear and helpfull.


  • Sharaf

    SharafSharaf

    Author Reply

    gr8 and very simple … i don’t have to be super in coding .. just follow the instructions and at the end everything will be working like charm 😉 .. one small issue, it’s if you may specify where to copy and paste the code as .h .m and the name it will be easier for the rest … my self it worked out with me 100% .. Thank you so much


  • Mike

    MikeMike

    Author Reply

    I cant get it to work, can someone send me the finished code?


  • Nel Martins

    Great tutorial. I have a question about the Accessory when a search is performed. Is there a way to set the Accessory to Disclosure Indicator to have the search list and non-search list appear identical?


  • Todd

    ToddTodd

    Author Reply

    Like Mike below, I can’t get this to work either; entering text in the search bar does not display search results (the entire list remains in the view). I am on Xcode 4.5, and my guess is that 4.5 does not wire up the search widget automatically, at least not the same way. When I look at the connections on RecipeBookViewController, I don’t see all the same connections as shown in your screenshot (see my screenshot below).


    • Todd

      ToddTodd

      Author Reply

      ah ha! My mistake — I used the ‘Search Bar’ component, instead of the ‘Search Bar and Search Display’ component. Now with the correct controller in place, search works perfectly.


      • Simon Ng

        Simon NgSimon Ng

        Author Reply

        Cool! Glad to hear the problem got solved.


  • Shalin Shah

    How can I make a search bar in a listView instead of a tableView?


  • napolux

    napoluxnapolux

    Author Reply

    Is there a way to get from the search tableview the original indexPath of the cell in the “parent” tableview?


  • Diogo

    DiogoDiogo

    Author Reply

    I just didn’t understand why you create that method with the scope parameter if you are not using.


  • ASH

    ASHASH

    Author Reply

    how to work with NSMutableArray? (that contains title and text for detailView – both are nsstring…)
    how to make it filter titles?!!


  • Guest

    GuestGuest

    Author Reply

    I got a problem… after entering the word in search bar nothing changes….


  • ASH

    ASHASH

    Author Reply

    I got a problem… after entering the word in search bar nothing changes. what to do?


  • Arseniy

    ArseniyArseniy

    Author Reply

    it just works 😉 thank you!


  • Jay Santos

    Jay SantosJay Santos

    Author Reply

    Great tutorial as always! Can you also have the recipe tweaked to be grouped as food kinds sections i.e. high calorie, low calorie, etc. and have the table display it with the header named as the sections. It’ll make this tutorial super complete.


  • Appsicode

    AppsicodeAppsicode

    Author Reply

    When adding the Predicate. Im getting and error “use of undeclared identifier ‘filtercontentForSearchText” can someone help with with this please.


    • HelloWorlD!

      it means the predicate has not yet being executed,

      just type the rest of the code and the problem should be gone
      🙂


  • Me Gusta

    Me GustaMe Gusta

    Author Reply

    Thanks for the tutorial – from an iOS newbie


  • Malkit Singh

    thanks for useful tut….


  • tiendh

    tiendhtiendh

    Author Reply

    It’s great


  • Mark Thien

    Mark ThienMark Thien

    Author Reply

    Hi Samuel, would you mind to provide us a download link for this project please? I got everything working except that when return from Detail View by tapping of upper left corner button, it goes back to the same Detail View screen then I have to tab again on the button to go back to the table view screen.


  • Michael Ozeryansky

    Thank you!


  • Basil Bourque

    Great tutorial. But it seems to have left out one step. The method:

    – (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    …needs to be updated. Rather than a single line of code:
    return [recipes count];
    …it needs an IF() statement to test if we are in Search mode. If searching, return count of “searchResults” rather than count of “recipes”.

    Complete method…

    – (NSInteger)tableView:(UITableView *)tableView
    numberOfRowsInSection:(NSInteger)section
    {
    if (tableView == self.searchDisplayController.searchResultsTableView) {
    return [searchResults count];
    } else {
    return [recipes count];
    }
    }


  • Alan

    AlanAlan

    Author Reply

    Excellent tutorials, more please!!!


  • Erik Fisher

    First of all; your tutorials are absolutely amazing! I discovered this site a couple of days ago and I’ve been sitting with it ever since!

    A quick question popped up during this one. At the prepare ForSegue I am able to pass the title to the DetailView, but I am struggling to pass along the image I also have in the DetailView.

    I was able to do it by changing the image names to be exactly the same as the recipeNames. That way I could use [UIImage imageNamed:[searchResults objectAtIndex:indexPath.row]];
    But that doesn’t seem like a very good way of doing it..

    Can you show me some coding magic on this topic?

    Thanks again!


  • Erik Fisher

    First of all; your tutorials are absolutely amazing! I discovered this site a couple of days ago and I’ve been sitting with it ever since!

    A quick question popped up during this one. At the prepare ForSegue I am able to pass the title to the DetailView, but I am struggling to pass along the image I also have in the DetailView.

    I was able to do it by changing the image names to be exactly the same as the recipeNames. That way I could use [UIImage imageNamed:[searchResults objectAtIndex:indexPath.row]];
    But that doesn’t seem like a very good way of doing it..

    Can you show me some coding magic on this topic?

    Thanks again!


  • rohan

    rohanrohan

    Author Reply

    Hey, great tutorial, but I get a SIGABRT error when I click on the tab I put the search bar in.


  • javifernandezr

    Very Useful


  • mevdev

    mevdevmevdev

    Author Reply

    Great tutorial. Thanks!


  • Lafayette Kirsi Noel

    Good Day Simon! I got stuck up in Displaying search results in searchResultsTableView. When I tried running it and search something, the app terminates and a SIGABRT will occur under main in ” return UIApplicationMain(argc, argv, nil, NSStringFromClass (RecipeBookAppDelegate class])); “.
    Im using this syntax of RMD from the previous tutorial’s comments

    Recipe *thisRecipe=[recipes objectAtIndex:indexPath.row];cell.textLabel.text=thisRecipe.name;

    in order to display the recipe names on tableview.. Im not quite sure if it’s connected to the problem in searching and displaying.


  • Giancarlo Leonio

    Awesome tutorial Simon! Just was I needed. I made a list of resources on this topic of implementing a Search Bar in TableView. Other may find useful: http://www.verious.com/board/Giancarlo-Leonio/implementing-an-ios-search-bar-in-table-view


  • Khalid Mehmood Awan

    things are getting a little difficult now 😀 ….

    anyways, excellent work…


  • Paul Lau

    Paul LauPaul Lau

    Author Reply

    Great tutorial !! ^_^

    Do you have any idea to customize the TableCell for UISearchDisplayController ? Like your Tutorial #4 – Customize Table View Cells for UITableView.

    Many Thanks…


    • EA

      EAEA

      Author Reply

      In cellForRowAtIndexPath, in the statement where you use searchResult array, you can manipulate the style of the cell.

      //forcing the cell to have disclosure indicator like the tableView.
      if (tableView == self.searchDisplayController.searchResultsTableView) {
      cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
      cell.textLabel.text = [searchResults objectAtIndex:indexPath.row];


  • Felix

    FelixFelix

    Author Reply

    Hey,
    I have some problems, it throws an error “can’t use in/contains operator with collection” when I try to write something into the searchbar.

    Here’s my code:

    //
    // RecipeViewController.m
    // CustomTableView
    //
    // Created by Simon on 1/1/13.
    // Copyright (c) 2013 Appcoda. All rights reserved.
    //

    #import “RecipeViewController.h”
    #import “Recipe.h”

    @interface RecipeViewController ()

    @end

    @implementation RecipeViewController {
    NSArray *recipes;
    NSArray *searchResults;
    }

    – (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
    {
    NSPredicate *resultPredicate = [NSPredicate
    predicateWithFormat:@”SELF contains[cd] %@”,
    searchText];

    searchResults = [recipes filteredArrayUsingPredicate:resultPredicate];
    }

    -(BOOL)searchDisplayController:(UISearchDisplayController *)controller
    shouldReloadTableForSearchString:(NSString *)searchString
    {
    [self filterContentForSearchText:searchString
    scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
    objectAtIndex:[self.searchDisplayController.searchBar
    selectedScopeButtonIndex]]];

    return YES;
    }

    – (id)initWithStyle:(UITableViewStyle)style
    {
    self = [super initWithStyle:style];
    if (self) {
    // Custom initialization
    }
    return self;
    }

    – (void)viewDidLoad
    {
    [super viewDidLoad];

    self.navigationItem.title = @”Minecraft IDs”;
    UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@”Back” style:UIBarButtonItemStyleBordered target:nil action:nil];
    [[self navigationItem] setBackBarButtonItem:backButton];

    // Create recipe array
    Recipe *recipe1 = [Recipe new];
    recipe1.name = @”Mushroom Risotto”;
    recipe1.detail = @”Delicious mushroom risotto made with vegetable broth, cream, and a variety of fresh vegetables. Serve as a side dish or filling main course.”;
    recipe1.imageFile = @”mushroom_risotto.jpg”;

    Recipe *recipe2 = [Recipe new];
    recipe2.name = @”Egg Benedict”;
    recipe2.detail = @”30 min”;
    recipe2.imageFile = @”egg_benedict.jpg”;

    Recipe *recipe3 = [Recipe new];
    recipe3.name = @”Full Breakfast”;
    recipe3.detail = @”20 min”;
    recipe3.imageFile = @”full_breakfast.jpg”;

    Recipe *recipe4 = [Recipe new];
    recipe4.name = @”Hamburger”;
    recipe4.detail = @”30 min”;
    recipe4.imageFile = @”hamburger.jpg”;

    Recipe *recipe5 = [Recipe new];
    recipe5.name = @”Ham and Egg Sandwich”;
    recipe5.detail = @”10 min”;
    recipe5.imageFile = @”ham_and_egg_sandwich.jpg”;

    recipes = [NSArray arrayWithObjects:recipe1, recipe2, recipe3, recipe4, recipe5, nil];
    }

    – (void)didReceiveMemoryWarning
    {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }

    #pragma mark – Table view data source

    – (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
    // Return the number of sections.
    return 1;
    }

    – (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
    if (tableView == self.searchDisplayController.searchResultsTableView) {
    return [searchResults count];

    } else {
    return [recipes count];

    }
    }

    – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    static NSString *CellIdentifier = @”Cell”;
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    // Configure the cell…
    if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    if (tableView ==self.searchDisplayController.searchResultsTableView) {
    Recipe *recipe = [searchResults objectAtIndex:indexPath.row];
    UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:100];
    recipeImageView.image = [UIImage imageNamed:recipe.imageFile];

    UILabel *recipeNameLabel = (UILabel *)[cell viewWithTag:101];
    recipeNameLabel.text = recipe.name;

    UILabel *recipeDetailLabel = (UILabel *)[cell viewWithTag:102];
    recipeDetailLabel.text = recipe.detail;
    }

    // Display recipe in the table cell
    Recipe *recipe = [recipes objectAtIndex:indexPath.row];
    UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:100];
    recipeImageView.image = [UIImage imageNamed:recipe.imageFile];

    UILabel *recipeNameLabel = (UILabel *)[cell viewWithTag:101];
    recipeNameLabel.text = recipe.name;

    UILabel *recipeDetailLabel = (UILabel *)[cell viewWithTag:102];
    recipeDetailLabel.text = recipe.detail;

    return cell;
    }

    /*
    // Override to support conditional editing of the table view.
    – (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
    {
    // Return NO if you do not want the specified item to be editable.
    return YES;
    }
    */

    /*
    // Override to support editing the table view.
    – (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
    {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
    // Delete the row from the data source
    [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }
    else if (editingStyle == UITableViewCellEditingStyleInsert) {
    // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }
    }
    */

    /*
    // Override to support rearranging the table view.
    – (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
    {
    }
    */

    /*
    // Override to support conditional rearranging of the table view.
    – (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
    {
    // Return NO if you do not want the item to be re-orderable.
    return YES;
    }
    */

    #pragma mark – Table view delegate

    – (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
    // Navigation logic may go here. Create and push another view controller.
    /*
    *detailViewController = [[ alloc] initWithNibName:@”” bundle:nil];
    // …
    // Pass the selected object to the new view controller.
    [self.navigationController pushViewController:detailViewController animated:YES];
    */
    }

    @end


    • Yanet

      YanetYanet

      Author Reply

      You have to put this in the search query (specify the attribute to search, ‘name’) :
      SELF.name contains[cd] %@

      Alsoto visualize the result have to put this (look the self before tableView):
      UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];


  • rajohns

    rajohnsrajohns

    Author Reply

    just in case anyone made the same mistake I did and clicking a search result always shows the same recipe detail:

    i had already implemented the didSelectRowAtIndexPath method to deselect the option. If you did this, make sure you put the “[tableView deselectRowAtIndexPath:indexPath animated:YES];” line AFTER the performSegueWithIdentifier line. Otherwise the row will be deselected, and the indexPath will not evaluate to anything in the prepareForSegue function when the search display is active.


  • Yanet

    YanetYanet

    Author Reply

    Issue:

    I’m working with a Customized Cell and the searchTableView is not picking those cells. What I mean is that I’m trying to change the background and size of the cells for the searchTableView so it looks more like my tableView before the search. However is not working. Any idea?


  • Htun Lin Aung

    i have a search bar with two scope bar buttons. if i click the search button, i need to check which scope bar button was clicked.
    How to check which button i clicked?


  • cyburt

    cyburtcyburt

    Author Reply

    Great stuff! Helped me out a lot…


  • Henry D’Andrea

    I keep getting a crash on line cell.textLabel.text = [recipes objectAtIndex:indexPath.row];

    Any help?


    • Jacob

      JacobJacob

      Author Reply

      perhaps the problem is that your recipes array is an array of dictionaries (something I would have done especially if I get the recipes through an api of some sort). If this is the case, you’re trying to set a dictionary in place of a string. try something like this: [[recipes objectAtIndex:indexPath.row] objectForKey:@”name”] where @”name” is the key of the name of the recipe in your dictionary.

      I don’t think Xcode would complain pre-compile since an array returns an (id).


  • Hannan

    HannanHannan

    Author Reply

    em facing a prblem that my search bar is displayed at the bottom of the page, can any one tell me abt this


  • Ali Alem

    Ali AlemAli Alem

    Author Reply

    Excellent tutorial. Works perfectly for me. I have one question: I would like to put the UISearchBar in the tableview header like in the Mail app. The problem is I don’t have a reference to the search bar using this tutorial cuz it’s hooked to the search display controller. I tried self.tableview.header.view = self.uisearchdisplaycontroller.searchbar; but this crashed. Any ideas?


  • Marc

    MarcMarc

    Author Reply

    Loved it! thank you guys so much!


  • Paul

    PaulPaul

    Author Reply

    Hi, i am also having an issue with the search bar for my customised ‘recipe’ as i have changed it to Fire Stations etc. I wonder if someone could spare some time to have a look at my code to see if they can identify the issue. As with some of the other comments, it kicks out the simulator and takes me to an error with SIGABRT at the following string;

    return UIApplicationMain(argc, argv, nil, NSStringFromClass([RecipeBookAppDelegate class]));

    Please be mindful that i have little to no programming knowledge and i am trying to teach myself. Any help would be greatly appreciated. Paul

    //

    // RecipeBookViewController.m

    // RecipeBook

    //

    // Created by Simon Ng on 14/6/12.

    // Copyright (c) 2012 Appcoda. All rights reserved.

    //

    #import “FireStationViewController.h”

    #import “StationDetailViewController.h”

    #import “Information.h”

    @interface FireStationViewController ()

    @end

    @implementation FireStationViewController {

    NSArray *stations;

    NSArray *searchResults;

    }

    @synthesize tableView = _tableView;

    – (void)viewDidLoad

    {

    [super viewDidLoad];

    Information *station1 = [Information new];

    station1.name = @”Alresford”;

    station1.prepTime = @”36″;

    station1.imageFile = @”36alresford.jpg”;

    station1.ingredients = [NSArray arrayWithObjects:@”Pound Hill”, @”Alresford”, @”SO24 9BP”, @””, @”Watch Manager – P Roach”, @””, @”Drill night”, @”Monday 19.00 – 21.00″, nil];

    Information *station2 = [Information new];

    station2.name = @”Alton”;

    station2.prepTime = @”05″;

    station2.imageFile = @”05alton.jpg”;

    station2.ingredients = [NSArray arrayWithObjects:@”Butts Road”, @”Alton”, @”Hampshire”, @”GU34 1LL”, @””, @”Watch Manager – I Craley”, @””, @”Drill night”, @”Thursday 18.30 – 21.30″, nil];

    Information *station3 = [Information new];

    station3.name = @”Andover”;

    station3.prepTime = @”31″;

    station3.imageFile = @””;

    station3.ingredients = [NSArray arrayWithObjects:@”London Street”, @”Andover”,@”SP10 2PF”,@””,@”Station Manager – M White”,@””,@”Drill night”,@”Monday 18.30 – 21.30″, nil];

    Information *station4 = [Information new];

    station4.name = @”Basingstoke”;

    station4.prepTime = @”01″;

    station4.imageFile = @”01basingstke.jpg”;

    station4.ingredients = [NSArray arrayWithObjects:@”West Ham Close”,@”Basingstoke”,@”RG22 6PH”,@””,@”Station Manager – D Graham”,@””,@”Drill night”,@”Tuesday 19.00 – 22.00″,@””, nil];

    Information *station5 = [Information new];

    station5.name = @”Beaulieu”;

    station5.prepTime = @”49″;

    station5.imageFile = @””;

    station5.ingredients = [NSArray arrayWithObjects:@”Off High Street”,@”Beaulieu”,@”SO42 7YF”,@””,@”Watch Manager – R Knight”,@””,@”Drill night”,@”Monday 19.00 – 22.00″, nil];

    Information *station6 = [Information new];

    station6.name = @”Bishops Waltham”;

    station6.prepTime = @”40″;

    station6.imageFile = @”40bishopswaltham.jpg”;

    station6.ingredients = [NSArray arrayWithObjects:@”Lower Lane”,@”Bishops Waltham”,@”SO32 1AS”,@””,@”Watch Manager – A J Smith”,@””,@”Drill night”,@”Monday 19.00 – 22.00″, nil];

    Information *station7 = [Information new];

    station7.name = @”Bordon”;

    station7.prepTime = @”03″;

    station7.imageFile = @”03bordon.jpg”;

    station7.ingredients = [NSArray arrayWithObjects:@”Conde Way”,@”Bordon”,@”Hampshire”,@”GU35 0XF”, @””, @”Watch Manager – P Hoban”,@””,@”Drill night”,@”Thursday 18.45 – 21.45″, nil];

    Information *station8 = [Information new];

    station8.name = @”Botley”;

    station8.prepTime = @”38″;

    station8.imageFile = @””;

    station8.ingredients = [NSArray arrayWithObjects:@”Winchester Street”,@”Botley”,@”Southampton”,@”Hampshire”,@”SO30 2EB”,@””,@”Watch Manager – M Woods”,@””, @”Drill night”,@”Tuesday 19.00 – 22.00″, nil];

    Information *station9 = [Information new];

    station9.name = @”Brockenhurst”;

    station9.prepTime = @”50″;

    station9.imageFile = @””;

    station9.ingredients = [NSArray arrayWithObjects:@”Lyndhurst Road”,@”Brockenhurst”,@”SO42 7RL”,@””,@”Watch Manager – K Baker”,@””,@”Drill night”,@”Tuesday 19.30 – 21.30″, nil];

    Information *station10 = [Information new];

    station10.name = @”Burley”;

    station10.prepTime = @”52″;

    station10.imageFile = @””;

    station10.ingredients = [NSArray arrayWithObjects:@”Ringwood Road”,@”Burley”,@”BH24 4BU”,@””,@”Watch Manager – T Gray”,@””,@”Drill night”,@”Monday 19.30 – 21.30″, nil];

    Information *station11 = [Information new];

    station11.name = @”Cosham”;

    station11.prepTime = @”23″;

    station11.imageFile = @””;

    station11.ingredients = [NSArray arrayWithObjects:@”Wayte Street”,@”Cosham”,@”Portsmouth”,@”PO6 3BS”,@””,@”Station Manager – B Gordon”, nil];

    Information *station12 = [Information new];

    station12.name = @”Droxford”;

    station12.prepTime = @”41″;

    station12.imageFile = @””;

    station12.ingredients = [NSArray arrayWithObjects:@”Union Lane”, @”Droxford”, @”Hampshire”, @”SO32 3QP”, @””, @”Watch Manager – K Sherfield”, @””, @”Drill night”, @”Monday 19.30 – 21.30″, nil];

    Information *station13 = [Information new];

    station13.name = @”Eastleigh”;

    station13.prepTime = @”32″;

    station13.imageFile = @””;

    station13.ingredients = [NSArray arrayWithObjects:@”Steele Close”, @”Eastleigh”, @”SO53 3AA”, @””, @”Station Manager – S Ransley”, @””, @”Drill night”, @”Monday 19.00 – 20.00″, nil];

    Information *station14 = [Information new];

    station14.name = @”Emsworth”;

    station14.prepTime = @”26″;

    station14.imageFile = @””;

    station14.ingredients = [NSArray arrayWithObjects:@”North Street”, @”Emsworth”, @”Hampshire”, @”PO10 7DD”, @””, @”Watch Manager – P Merry”, @””, @”Drill night”, @”Wednesday 19.00 – 21.00″, nil];

    Information *station15 = [Information new];

    station15.name = @”Fareham”;

    station15.prepTime = @”17″;

    station15.imageFile = @””;

    station15.ingredients = [NSArray arrayWithObjects:@”Station Approach”, @”Fareham”, @”PO16 0HZ”, @””, @”Station Manager – P Coates”, @””, @”Drill night”, @”Tuesday 19.00 – 21.00″, nil];

    Information *station16 = [Information new];

    station16.name = @”Fleet”;

    station16.prepTime = @”04″;

    station16.imageFile = @””;

    station16.ingredients = [NSArray arrayWithObjects:@”89 Connaught Road”, @”Fleet”, @”Hampshire”, @”GU51 3LP”, @””, @”Watch Manager – C Gregory”, @””, @”Drill night”, @”Monday 19.15 – 21.15″, nil];

    Information *station17 = [Information new];

    station17.name = @”Fordingbridge”;

    station17.prepTime = @”47″;

    station17.imageFile = @””;

    station17.ingredients = [NSArray arrayWithObjects:@”Station Road”, @”Fordingbridge”, @”SP6 1JN”, @””, @”Watch Manager – P White”, @””, @”Drill night”, @”Wednesday 19.00 – 21.00″, nil];

    Information *station18 = [Information new];

    station18.name = @””;

    station18.prepTime = @””;

    station18.imageFile = @””;

    station18.ingredients = [NSArray arrayWithObjects:@””, @””, @””, @””, @””, @””, @”Drill night”, @”Wednesday 19.00 – 21.00″, nil];

    Information *station19 = [Information new];

    station19.name = @””;

    station19.prepTime = @””;

    station19.imageFile = @””;

    station19.ingredients = [NSArray arrayWithObjects:@””, @””, @””, @””, @””, @””, @”Drill night”, @”Wednesday 19.00 – 21.00″, nil];

    Information *station20 = [Information new];

    station20.name = @””;

    station20.prepTime = @””;

    station20.imageFile = @””;

    station20.ingredients = [NSArray arrayWithObjects:@””, @””, @””, @””, @””, @””, @”Drill night”, @”Wednesday 19.00 – 21.00″, nil];

    Information *station = [Information new];

    station.name = @””;

    station.prepTime = @””;

    station.imageFile = @””;

    station.ingredients = [NSArray arrayWithObjects:@””, @””, @””, @””, @””, @””, @”Drill night”, @”Wednesday 19.00 – 21.00″, nil];

    stations = [NSArray arrayWithObjects:station1, station2, station3, station4, station5, station6, station7, station8, station9, station10, station11, station12, station13, station14, station15, station16, station17, station18, station19, station20, station, nil];

    }

    – (void)viewDidUnload

    {

    [super viewDidUnload];

    // Release any retained subviews of the main view.

    }

    – (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

    {

    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);

    }

    – (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    {

    return [stations count];

    }

    – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    {

    static NSString *simpleTableIdentifier = @”RecipeCell”;

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];

    if (cell == nil) {

    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];

    }

    Information *station = [stations objectAtIndex:indexPath.row];

    cell.textLabel.text = station.name;

    return cell;

    }

    – (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    if ([segue.identifier isEqualToString:@”showRecipeDetail”]) {

    StationDetailViewController *destViewController = segue.destinationViewController;

    NSIndexPath *indexPath = nil;

    if ([self.searchDisplayController isActive]) {

    indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];

    destViewController.station = [searchResults objectAtIndex:indexPath.row];

    } else {

    indexPath = [self.tableView indexPathForSelectedRow];

    destViewController.station = [stations objectAtIndex:indexPath.row];

    }

    }

    }

    – (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope

    {

    NSPredicate *resultPredicate = [NSPredicate

    predicateWithFormat:@”SELF contains[cd] %@”,

    searchText];

    searchResults = [stations filteredArrayUsingPredicate:resultPredicate];

    }

    #pragma mark – UISearchDisplayController delegate methods

    -(BOOL)searchDisplayController:(UISearchDisplayController *)controller

    shouldReloadTableForSearchString:(NSString *)searchString

    {

    [self filterContentForSearchText:searchString

    scope:[[self.searchDisplayController.searchBar scopeButtonTitles]

    objectAtIndex:[self.searchDisplayController.searchBar

    selectedScopeButtonIndex]]];

    return YES;

    // Hide bottom tab bar in the detail view

    // destViewController.hidesBottomBarWhenPushed = YES;

    }

    @end


  • don

    dondon

    Author Reply

    Hi,

    Using the code below from Appcoda tutorial. Code is crashing at this line “self.searchResults = [[self.searchSet filteredArrayUsingPredicate:resultPredicate] mutableCopy];”

    I have spent significant time but am unable to understand why it should crash. Search Results is working properly and is filtering the data.

    // SEARCH BAR: Par1: Implement filter using NSPRedicate
    – (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
    {
    NSPredicate *resultPredicate = [NSPredicate
    predicateWithFormat:@”SELF contains[cd] %@”,
    searchText];

    self.searchResults = [[self.searchSet filteredArrayUsingPredicate:resultPredicate] mutableCopy];
    // NSLog(@”%u”,[searchResults count]);
    }

    //Search display controller delegate
    -(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
    {
    [self filterContentForSearchText:searchString
    scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
    objectAtIndex:[self.searchDisplayController.searchBar
    selectedScopeButtonIndex]]];

    return YES;
    }

    //Table view controller
    – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
    {

    static NSString *simpleTableIdentifier = @”prototypecell”;
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];

    if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
    }
    searchSet =[object objectForKey:@”levelName”];
    // NSLog(@”%@”,searchSet);

    // Configure the cell

    if (tableView == self.searchDisplayController.searchResultsTableView) {
    NSLog(@”crash here”);
    cell.textLabel.text = [searchSet mutableCopy];
    }else {
    cell.textLabel.text = [searchSet mutableCopy];

    }

    // cell.textLabel.text = [searchSet mutableCopy];

    return cell;
    }


  • Arthur

    ArthurArthur

    Author Reply

    Hey, can you maybe make a tutorial about how to index this recipe book? That would be great! Awesome tutorial!


  • Michael Mork

    Thank you…


  • CEMSOFT SOFTWARE

    thanks, great tutorial.


  • dd

    dddd

    Author Reply

    Hi,
    I am trying to implement the code for selecting a cell, but the selection is not responding. The cell highlights but nothing happens. Thanks


  • Madhur

    MadhurMadhur

    Author Reply

    error:–
    no visible @interface for uiviewcontroller declares the selector ‘filter content for search text’


  • Tam Vo

    Tam VoTam Vo

    Author Reply

    Nice tutorial, thanks a lot


  • Tyra

    TyraTyra

    Author Reply

    hi , the search bar works perfectly fine . but after i searched for a specific recipe , found it but i cant open it from the search bar . but when i select it from the table view , i can open it as always 🙁


    • Jacob

      JacobJacob

      Author Reply

      the problem is because you are retrieving two different cells depending on if its a search or if its the full list. Its similar to the problem I’m having. I can solve it, but I was looking for better ways of doing it (thats why im here).

      My solution is to make an outlet for the table view. By now you already know how to make an outlet but if not, its something you should learn before working with tables.

      then change:
      UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
      if (cell == nil) {
      cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
      }

      into :
      UITableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];

      where _tableView is your name you gave to the outlet (add the underscore). I haven’t tried it with segues but I don’t see any reason it shouldn’t work


      • Komokurono

        KomokuronoKomokurono

        Author Reply

        I’m afraid this won’t help. Just tried it.


  • Sabir

    SabirSabir

    Author Reply

    Awesome………Thanks for this tutorial…………..


  • toshi

    toshitoshi

    Author Reply

    I had some issue. When I typed in the search bar, it is covered up and invisible.
    How I fixed is put the search bar into the Table View layer. Now it works.


    • hupili

      hupilihupili

      Author Reply

      +1 . This is worth a note in the OP. Same issue and solution on XCode 5 and iOS 7. Without this tip, the searchbar is covered by navigation bar


  • toshi

    toshitoshi

    Author Reply

    #import “ViewController.h”

    #import “detailViewController.h” // I realized it’s not good practice. The first letter shold be the upper case

    @interface ViewController ()

    {

    NSMutableArray *_recipes;

    NSString *_recipeName;

    NSArray *_searchResults;

    }

    @end

    @implementation ViewController

    – (void)viewDidLoad

    {

    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    self.tableView.delegate = self;

    self.tableView.dataSource = self;

    _recipes = [NSMutableArray arrayWithObjects:@”Egg Benedict”,@”Mushroom Risotto”,@”Full Breakfast”, @”Hamburger”,@”Ham and Egg Sandwich”, @”Cream Brelee”,@”White Chocolate Donut”,@”Starbucks Coffee”,@”Vegetable Curry”, @”Instant Noodle With Egg”,@”Noodle with BBQ Pork”, @”Japanese Noodle with Pork”,@”Green Tea”, @”Thai shripm Cake”, @”Angry Birds Cake”,@”Ham and Cheese Panini”,nil];

    }

    – (void)didReceiveMemoryWarning

    {

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

    }

    # pragma mark Dlegate method

    // Data source protocol

    – (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    {

    if(tableView == self.searchDisplayController.searchResultsTableView)

    {

    return [_searchResults count];

    }

    else

    {

    return [_recipes count];

    }

    }

    – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    {

    NSString *simpleTableIdentifier = @”RecipeCell”;

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];

    if (cell == nil)

    {

    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];

    }

    if(tableView == self.searchDisplayController.searchResultsTableView)

    {

    cell.textLabel.text = _searchResults[indexPath.row];

    }

    else

    {

    cell.textLabel.text = _recipes[indexPath.row];

    }

    NSLog(@”%@”,_searchResults);

    return cell;

    }

    // Delegate Protocol

    – (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    {

    //NSLog(@”row %i and section %i”,indexPath.row,indexPath.section);

    if(tableView == self.searchDisplayController.searchResultsTableView)

    {

    _recipeName = _searchResults[indexPath.row];

    }

    else

    {

    _recipeName = _recipes[indexPath.row];

    }

    [self performSegueWithIdentifier:@”CellSelectionSegue” sender:self];

    }

    # pragma mark Segue method

    -(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

    {

    NSLog(@”segue”);

    detailViewController *detailVC = segue.destinationViewController;

    detailVC.string = _recipeName;

    NSLog(@”%@”,_recipeName);

    }

    # pragma mark Searchbar datasource

    – (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope

    {

    NSPredicate *resultPredicate = [NSPredicate

    predicateWithFormat:@”SELF contains[cd] %@”,

    searchText];

    _searchResults = (NSArray *)[_recipes filteredArrayUsingPredicate:resultPredicate];

    //NSLog(@”%@”,_searchResults);

    }

    -(BOOL)searchDisplayController:(UISearchDisplayController *)controller

    shouldReloadTableForSearchString:(NSString *)searchString

    {

    [self filterContentForSearchText:searchString

    scope:[[self.searchDisplayController.searchBar scopeButtonTitles]

    objectAtIndex:[self.searchDisplayController.searchBar

    selectedScopeButtonIndex]]];

    return YES;

    }

    – (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption

    {

    [self filterContentForSearchText:self.searchDisplayController.searchBar.text

    scope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];

    return YES;

    }

    @end

    This also works


  • chandankr

    chandankrchandankr

    Author Reply

    Awesome Tutorial!!


  • d_alifda

    d_alifdad_alifda

    Author Reply

    Hi, this is a great tutorial. When I just started using Xcode 4.5 (storyboards mode) I succesfully applied this tutorial into my tableView (populated manually with NSArray of strings). But when I changed the tableView datasource into data from XML parser, the search display controller doesn’t work.
    As I start typing a character into the search bar, the ‘transparent layer’ disappears and only showing the original tableView behind (as in your case, table view containing the array ‘recipes’, instead of ‘searchResults’).
    The only changes I made were the assignment of the array ‘recipes’ on viewDidLoad method as follows:

    xmlParser = [[XMLParser alloc] loadXMLByURL:@”someURL”];
    recipes = [xmlParser allrecipes];

    What could possibly be missing here? Still confused X_X.
    P.S.: I got no problems with the XML parsing part since the tableView is populated correctly


  • Tiago De Barros Hillesheim

    I’m confused with the method filtercontentForSearchText:
    It’s a custom method since it’s not defined anywhere. So why is that “scope” parameter? it’s not used inside the method …

    And the searchDisplayController:shouldReloadTableForSearchString: method doesn’t show up
    in the code hint, which is very annoying.

    anyway, worked for me in the end. thanks


  • Steven

    StevenSteven

    Author Reply

    Great tutorial but is it possible to have a search bar to lookup the entire App contents rather than just the table view ?


  • shasvat

    shasvatshasvat

    Author Reply

    Really, if we follow all your steps application will work without a single warning…


  • vishnuvarthan

    your code works great but the problem is when i manually insert a new data it appears in the table but search bar is not searching the newly inserted data .help !!!


  • Hiren Patel

    Hi,
    Can i use this methods for UITextField?
    And If not than How can I customize the view of UISearchBar by replacing it by my custom UITextfield?


  • Kritbovorn Taweeyossak

    UISearchDisplayController , searchDisplayController is deprecated :first deprecated in iOS 8

    can solve this error Please.


  • cindy

    cindycindy

    Author Reply

    searchDisplayController is deprecated in IOS 8! Someone please help 🙁


    • cocoiws

      cocoiwscocoiws

      Author Reply

      I have the same problem 🙁 any boby knows how to update it? tks


  • Eric

    EricEric

    Author Reply

    Great tutorial but iOS 8.0 does not support “searchDisplayController” anymore..
    anyplan to update this tutorial ?


  • Phil

    PhilPhil

    Author Reply

    thanks Simon you made my day !


  • sazzadhusen iproliya

    great tutorial …………..helpfull as


  • Marq

    MarqMarq

    Author Reply

    is there a swift version?


  • Charles Robertson

    One word. Awesome…


  • Son Go Han

    Son Go HanSon Go Han

    Author Reply

    Hello. I followed this tutorial but when I text into the search bar, it couldn’t search anything like the picture below. I got this issue when using Xcode 9:
    This is my source code:
    //
    // ViewController.m
    // Accessories Manager
    //
    // Created by Hackintosh on 9/23/17.
    // Copyright © 2017 Hackintosh. All rights reserved.
    //

    #import “ViewController.h”
    #import “AccessoryDetailViewController.h”

    @interface ViewController ()

    @end

    @implementation ViewController
    {
    NSArray *recipes;
    NSArray *searchResults;
    }

    @synthesize tableView; // Add this line of code

    – (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    recipes = [NSArray arrayWithObjects:@”Egg Benedict”, @”Mushroom Risotto”, @”Full Breakfast”, @”Hamburger”, @”Ham and Egg Sandwich”, @”Creme Brelee”, @”White Chocolate Donut”, @”Starbucks Coffee”, @”Vegetable Curry”, @”Instant Noodle with Egg”, @”Noodle with BBQ Pork”, @”Japanese Noodle with Pork”, @”Green Tea”, @”Thai Shrimp Cake”, @”Angry Birds Cake”, @”Ham and Cheese Panini”, nil];
    }

    – (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }

    – (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    if ([segue.identifier isEqualToString:@”showAccessoryDetail”]) {

    NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];

    AccessoryDetailViewController *destViewController = segue.destinationViewController;

    destViewController.accessoryName = [recipes objectAtIndex:indexPath.row];

    }

    }

    – (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope

    {
    NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@”SELF contains[cd] %@”, searchText];

    searchResults = [recipes filteredArrayUsingPredicate:resultPredicate];

    }

    -(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString

    {

    [self filterContentForSearchText:searchString scope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
    return YES;

    }

    – (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {

    if (tableView == self.searchDisplayController.searchResultsTableView) {
    return [searchResults count];

    } else {
    return [recipes count];
    }
    }

    – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    static NSString *accessoryTableIdentifier = @”AccessoryCell”;
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:accessoryTableIdentifier];

    if(cell == nil)
    {
    cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:accessoryTableIdentifier];
    }

    if (tableView == self.searchDisplayController.searchResultsTableView) {
    cell.textLabel.text = [searchResults objectAtIndex:indexPath.row];
    } else {
    cell.textLabel.text = [recipes objectAtIndex:indexPath.row];
    }

    return cell;
    }

    – (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    return 71;
    }
    @end


  • Chinmay

    ChinmayChinmay

    Author Reply

    Project is missing from dropBox https://dl.dropboxusercontent.com/u/2857188/RecipeBook_Search_Bar.zip

    please add the project so that we can refer it.


Leave a Reply to cindy
Cancel Reply

Shares