How to Add Search Into a Table View

Nick Martin

This post is also available in: Chinese (Simplified), Japanese

This is a post by iOS Tutorial Team Member Nicolas Martin, an independent iOS developer at nmappworks.

Update: We have a new version of this table view search tutorial fully updated to iOS 8 and Swift – check it out!

In the mobile app world, people want their information fast, and they want it now!

iOS users expect their data to be available on-demand and presented quickly. Furthermore, they expect this to all happen in an easy to use and intuitive manner. It’s a tall order, to be sure!

Many UIKit based applications utilize the UITableView as a way to navigate through data, since scrolling is natural and fast. But what about the cases where there are large, even huge, amounts of data to sift through? With large datasets, scrolling through massive lists becomes slow and frustrating – so it’s vitally important to allow users to search for specific items.

Lucky for us, UIKit includes UISearchBar which seamlessly integrates with your table views and allows for quick, responsive filtering of information.

In this tutorial, you’ll learn how to add search capability into your UITableView based apps, including dynamic filtering and adding an optional Scope Bar. In the end, you’ll know how to make your apps much more user friendly and satisfy your users urgent demands!

Don’t Fear the Bar!

The ability to search a large table view is something that today’s users expect; when they find it isn’t present, they won’t be happy campers!

Don’t let this happen to your users.
Always give them a search option.

The problem is the UISearchBar can be confusing when you first look at it, because it isn’t very well documented and figuring out how to get all the pieces to fit together can be quite tricky.

However, once you work with the Search Bar a bit, you’ll find that it’s not nearly as frightening as you might expect – especially after you go through this tutorial!

When you look at the UISearchBar, you’ll discover it’s kind of like a lazy layabout. It doesn’t do any of the work of searching at all! The class simply provides a standard interface that users have come to expect from their iOS apps. It’s more like a middle-class manager in that respect; it’s great at delegating tasks to others. (Like my old boss!)

The UISearchBar class communicates with a delegate protocol to let the rest of your app know what the user is doing. All of the actual functions for string matching and other operations will be written by you. Although this may seem a tad scary at first (and more than a little unfair!), writing custom search functions gives you tight control over how results are returned specifically in your app. Your users will appreciate searches that are intelligent — and fast.

In this tutorial you’ll build a searchable Candy app which is based on a table view. (Mmmm, candy!)

But first — a quick road map of where this tutorial will take you:

  • Candy Class: You’ll build a custom object that will allow your search function to search through the sample data (and also satisfy those munchies).
  • Table View: Here you’ll quickly go through the steps of setting up a table view. If you already know how to do this, you can quickly breeze through this section.
  • Search Bar: You’ll implement a search bar class onto your view controller so you can introduce some search functionality.
  • Filtered Array: Here you’ll learn how to manipulate a filtered array to handle your new search function.
  • Sending Data: This will serve as a reinforcement to the changes that are necessary to things like navigation when dealing with a search bar
  • Scope Bar: Here you’ll experience a powerful feature of the UISearchBar class: a scope bar for further zeroing in on search results.
  • Hiding the UISearchBar: This last section will show you how to perform a popular feature – hiding the search bar until the user needs it!

Ready for some sugar-coated search results? Read on!

I Want Candy

I'm getting hungry just working on this tutorial!

I’m getting hungry just working on this tutorial!

In XCode, go to “File \ New \ Project…” and choose iOS\Application\Single View Application. Name the project “CandySearch” and make sure that “Use Storyboards” and “Use Automatic Reference Counting” are checked. Finally make sure that iPhone is selected for “Device” and click Next. Save the project at a location of your choice.

Start by clearing out some of the default files so you can truly start from scratch. In the Project Navigator, select ViewController.h and ViewController.m, right-click, select Delete, and then click “Move to Trash”. Then open up the MainStoryboard.storyboard, select the only view controller and delete it.

Now that you have a fresh project to work with, start by creating the storyboard. From the Object Browser (the lower half of the right sidebar) drag out a Navigation Controller to add iOS’s built-in navigation logic to our project. This will create two views on the storyboard – one that represents the navigation controller and one that will be the UITableView that will be the initial screen of the application.

One final view controller will serve as the detail view controller that is displayed when the user navigates or searches the table. Drag a View Controller object onto the storyboard and link the two views by control-dragging from the Table View to the new view controller and selecting “Push” as the modal segue from the popup. As of now, this is how your project should look:

Setting Up the Candy Class

Next you will create a model class to keep track of the information about each piece of candy you’re displaying, such as its category and name.

To do this, create a new file with the iOS\Cocoa Touch\Objective-C class template. Name the class Candy, and make it a subclass of NSObject.

Open up Candy.h and replace its contents with the following:

    #import <Foundation/Foundation.h>
 
    @interface Candy : NSObject {
        NSString *category;
        NSString *name;
    }
 
    @property (nonatomic, copy) NSString *category;
    @property (nonatomic, copy) NSString *name;
 
    + (id)candyOfCategory:(NSString*)category name:(NSString*)name;
 
    @end

This object has two properties that can be referenced the category of the candy, and the name of the candy. When the user searches for a candy in your app, you’ll be referencing the name property against the user’s search string. You’ll see how the category string will become important near the end of this tutorial when we implement the Scope Bar.

To finish making this object, replace the contents of Candy.m with the following code:

    #import "Candy.h"
 
    @implementation Candy
    @synthesize category;
    @synthesize name;
 
    + (id)candyOfCategory:(NSString *)category name:(NSString *)name
    {
        Candy *newCandy = [[self alloc] init];
        newCandy.category = category;
        newCandy.name = name;
        return newCandy;
    }
 
    @end

The method above gives your custom object a way to create a new instance of the Candy object which contains the name and category passed to the method. You’ll populate your table from the data stored in these Candy objects, which will allow you to easily filter the data using your search methods.

Now we are ready to set up the UITableView that our UISearchBar will filter!

Please set the UITableViewController, dear…

Next you will set up a UITableView that will work with the UISearchBar. Create a new file with the iOS\Cocoa Touch\Objective-C class template. Name the class CandyTableViewController, and make it a subclass of UITableViewController.

We will start by adding an array for the sample data. Open CandyTableViewController.h and add the following code below the @interface line:

    @property (strong,nonatomic) NSArray *candyArray;

Now for some quick edits to CandyTableViewController.m in order to finish the sample table. First, clean out some of the default code in the project that won’t be required. Remove all the code beginning with -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath to the end of the file (except the @end).

Also remove the numberOfSectionsInTableView: method, as it won’t be necessary in this app.

At the top of the file, import Candy.h so the table view controller understands this object.

    #import "Candy.h"

Now synthesize the candyArray below the @implementation line.

    @synthesize candyArray;

Now that you’ve connected the view controller with the Candy object, you can use the candyOfCategory:name: method to add some data. In this tutorial, you only need to create a limited number of values to illustrate how the search bar works; in a production app, you might have thousands of these searchable objects. But whether an app has thousands of objects to search or just a few, the methods used will remain the same. Scalability at it’s finest!

In viewDidLoad, clear out the templated comments and add the following code to provide some sample data:

    // Sample Data for candyArray
    candyArray = [NSArray arrayWithObjects:
                  [Candy candyOfCategory:@"chocolate" name:@"chocolate bar"],
                  [Candy candyOfCategory:@"chocolate" name:@"chocolate chip"],
                  [Candy candyOfCategory:@"chocolate" name:@"dark chocolate"],
                  [Candy candyOfCategory:@"hard" name:@"lollipop"],
                  [Candy candyOfCategory:@"hard" name:@"candy cane"],
                  [Candy candyOfCategory:@"hard" name:@"jaw breaker"],
                  [Candy candyOfCategory:@"other" name:@"caramel"],
                  [Candy candyOfCategory:@"other" name:@"sour chew"],
                  [Candy candyOfCategory:@"other" name:@"peanut butter cup"],
                  [Candy candyOfCategory:@"other" name:@"gummi bear"], nil];
 
    // Reload the table
    [self.tableView reloadData];

Replace the contents of tableView:numberOfRowsInSection: with the following line that returns the size of the candyArray:

return [candyArray count];

Add the following code above the final @end:

-(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];
    }
    // Create a new Candy Object
    Candy *candy = nil;
    candy = [candyArray objectAtIndex:indexPath.row];
    // Configure the cell
    cell.textLabel.text = candy.name;
    [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
    return cell;
}

First, you tell the table view controller what to display for each row. You then access the candyArray object, reference the indexPath to decide which Candy object to pull, and then use that Candy object to populate the UITableViewCell.

You’ll need to set up the storyboard to recognize this code. Switch to MainStoryboard.storyboard, select the Root View Controller and change the Class field in the Identity Inspector (third tab on the top half of the right sidebar) to CandyTableViewController.

Then select the table view and wire the dataSource and delegate to the View Controller by switching to the Connections Inspector (it’s the sixth tab on the top half of the right sidebar) and dragging from each outlet to the Candy Table View Controller on the left sidebar.

Double click the title to change it from the rather unattractive “Root View Controller” title to “CandySearch”.

Save your changes and build and run. You now have a working table view! So much candy…so little time! We need…a UISearchBar!

Setting Up the UISearchBar

Now you’re ready to set up the UISearchBar! Start by opening up the storyboard and dragging a Search Bar and Search Display Controller object to the table view controller. Be careful — this is different from the Search Bar object, which is also available. Position the Search Bar between the Navigation bar and the Table View.

Note: Not sure what’s meant by a search display controller? According to Apple’s own documentation, a search display controller “manages display of a search bar and a table view that displays the results of a search of data managed by another view controller.

You initialize a search display controller with both a search bar and a view controller responsible for managing the original content to be searched. When the user begins a search action, the search display controller is responsible for superimposing the search interface over the original view controller’s view, and showing the search results. The results are displayed in a table view that’s created by the search display controller.”

So basically, the search display controller added above handles the task of showing the filtered data from a search in a separate view controller that you don’t have to worry about :]

UISearchBar Options in the Attributes inspector

While in the storyboard, take a moment to review the properties available for the Search Bar object. You may not use all of these, but knowing what’s available in the Attributes inspector is always valuable when working with a new UIKit component.

  • Text: This will change the actual string value that is present in the search bar. As your app has no need to have a default value in the search bar, you won’t need this.
  • Placeholder: This does exactly what you might expect – it allows you to put the light gray text in the Search bar that tells the user what the search bar can be used for. In the case of the Candy app, use something such as “Search for Candy”.
  • Prompt: This text will appear directly above the search bar. This is good for apps that have complicated search mechanisms, where the user might need instructions. (But in this app, the Placeholder text should be pretty clear!)
  • Style & Tint: These options allow you to customize the appearance of your search bar. The options are almost identical to those of the UINavigationBar and it is normally advisable to have your UISearchBar match your UINavigationBar for harmonious design.
  • Show Search Results Button: Provides a button on the right side of the search bar for performing functions such as displaying recent searches or showing the last search results. Interaction with this button is managed through the Search Bar Delegate methods.
  • Show Bookmarks Button: Shows the standard blue oval bookmarks icon in the right hand side of the search bar. Users expect this to bring up a list of their saved bookmarks. Like the search results button, this too is managed through the Search Bar Delegate methods.
  • Show Cancel Button: This button allows users to close the separate view controller that is generated by the search bar. Leave this unchecked, as the search bar will automatically show and hide the Cancel button when the user is in Search mode.
  • Shows Scope Bar & Scope Titles: The scope bar allows users to refine their search by limiting the results to a certain category, or scope. In a music application, for example, this bar may show choices such as Artists, Albums or Genres. For now, leave this box unchecked; you will implement your own scope bar later in this tutorial.
  • Capitalize, Correction & Keyboard: These are options that have been borrowed from the normal UITextField options and allow you to change your search bar’s behavior. For example, if the user will be searching on proper nouns like businesses or last names, you may want to consider turning off correction as it will be annoying to users. In this tutorial, the candy names are all common nouns, so keep autocorrect enabled.

Note: Knowing the available options allows you to reduce development time and be more efficient. So as a general note for your future iOS development, always take the time to get acquainted with the resources available :]

Setting Up the UISearchBarDelegate

After setting up the storyboard, you’ll need to do some coding work to get the search bar working. Add theUISearchBarDelegate and UISearchDisplayDelegate classes to the CandyTableViewController. To do this, switch to CandyTableViewController.h and replace:

@interface CandyTableViewController : UITableViewController

with:

@interface CandyTableViewController : UITableViewController <UISearchBarDelegate, UISearchDisplayDelegate>

In addition, add an IBOutlet for the search bar and a new “filteredCandyArray” which will hold our search results.

@property (strong,nonatomic) NSMutableArray *filteredCandyArray;
@property IBOutlet UISearchBar *candySearchBar;

Don’t forget to synthesize the new properties in CandyTableViewController.m:

@synthesize filteredCandyArray;
@synthesize candySearchBar;

Of course, now that you have an outlet, you need to wire the search bar on your storyboard to the outlet. Switch to the storyboard, select the Candy Table View controller, switch to the Connections Inspector, and drag a connection from the candySearchBar outlet to the Search Bar on the main screen.

Compile and run now, and you’ll get the search bar on the app — but it won’t filter anything yet! In order to do this, you’ll have to set up the filteredCandyArray.

Setting Up the Filtered Array

First you will have to initialize the NSMutableArray. You can initialize the array with the size of the candyArray, as it isn’t possible to have more filtered values than the number of values that we started with. Add the following line of code to viewDidLoad in CandyTableViewController.m where we set the candyArray, but before the [self.tableView reloadData]:

    // Initialize the filteredCandyArray with a capacity equal to the candyArray's capacity
    self.filteredCandyArray = [NSMutableArray arrayWithCapacity:[candyArray count]];

Add the following code to the end of the file:

#pragma mark Content Filtering
-(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
    // Update the filtered array based on the search text and scope.
    // Remove all objects from the filtered search array
    [self.filteredCandyArray removeAllObjects];
    // Filter the array using NSPredicate
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.name contains[c] %@",searchText];
    filteredCandyArray = [NSMutableArray arrayWithArray:[candyArray filteredArrayUsingPredicate:predicate]];
}

The above method will filter candyArray based on searchText (which is the search string entered by the user), and will put the results in filteredCandyArray. This filter method clears out any previous filtered search results by calling the “removeAllObjects” method. After the array has been cleared, a NSPredicate is used to filter the candy array based on the search string.

NSPredicate can filter an array using a simple condition string. Notice the format of the NSPredicate:

@"SELF.name contains[c] %@",searchText

Look a little confusing? Fear not; it’s actually fairly simple. SELF.name tells the NSPredicate to look at the “name” property of the Candy objects in the candyArray. “contains[c]” tells the predicate to search the “name” property for the provides text string, which is the search text in this case, in a case-insensitive manner.

Next, add the following code to the end of the file:

#pragma mark - UISearchDisplayController Delegate Methods
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
    // Tells the table data source to reload when text changes
    [self filterContentForSearchText:searchString scope:
     [[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
    // Return YES to cause the search result table view to be reloaded.
    return YES;
}
 
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
    // Tells the table data source to reload when scope bar selection changes
    [self filterContentForSearchText:self.searchDisplayController.searchBar.text scope:
     [[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];
    // Return YES to cause the search result table view to be reloaded.
    return YES;
}

This code sets up the UISearchDisplayController Delegate methods that will call the content filtering function when the the user enters a search query.

The first method runs the text filtering function whenever the user changes the search string in the search bar. The second method will handle the changes in the Scope Bar input. You haven’t yet added the Scope Bar in this tutorial, but you might as well add this UISearchBarDelegate method now since you’re going to need it later.

Compile and run the app now; you’ll notice that using the Search Bar still does not bring up any filtered results. What gives? This is simply because you haven’t yet written the code to let cellRowForIndexPath: know when to use the normal data vs. the filtered data. Replace:

	candy = [candyArray objectAtIndex:[indexPath row]];

with:

    // Check to see whether the normal table or search results table is being displayed and set the Candy object from the appropriate array
    if (tableView == self.searchDisplayController.searchResultsTableView) {
        candy = [filteredCandyArray objectAtIndex:indexPath.row];
    } else {
        candy = [candyArray objectAtIndex:indexPath.row];
    }

This code tests to see if the currently displayed tableView is the search table or the normal table. If it is indeed the search table, the data is taken from the filteredCandyArray. Otherwise, the data comes from the full list of items. Recall that the search display controller automatically handles showing and hiding the results table, so all your code has to do is provide the correct data (filtered or non-filtered) depending on which table view is currently displaying.

You’ll have to do something similar with numbersOfRowsInSection: since the number of rows for the filtered vs. non-filtered array are very likely going to be different! Replace the current contents of the method with:

// Check to see whether the normal table or search results table is being displayed and return the count from the appropriate array
if (tableView == self.searchDisplayController.searchResultsTableView) {
    return [filteredCandyArray count];
} else {
    return [candyArray count];
}

Compile and run the app. You’ve got a functioning Search Bar that filters the rows of the main table! Huzzah! Play with the app for a bit to see how the user can search for various candies.

Note: You’ve probably noticed that that the if/else logic found in the numberOfRowsInSection: method is reused quite a few times. This is important when working with the Search Bar Display Controller and omitting this if/else check may result in bugs that will be difficult to track down. Just remember that the filtered results do not appear in the same table view as the main table. They are actually completely separate table views, but Apple has designed them in such a way that the experience is seamless for the end user — at the expense of being confusing to the novice developer!

Sending Data to a Detail View

When sending information to a detail view controller, you need to ensure that the view controller knows which table view the user is working with: the full table list, or the search results. The code for this will be similar to the code that we wrote in numbersOfRowsInSection: and cellForRowAtIndexPath: methods. Add the following code to the end of your CandyTableViewController.m file:

#pragma mark - TableView Delegate
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Perform segue to candy detail
    [self performSegueWithIdentifier:@"candyDetail" sender:tableView];
}
 
#pragma mark - Segue
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([[segue identifier] isEqualToString:@"candyDetail"]) {
        UIViewController *candyDetailViewController = [segue destinationViewController];
        // In order to manipulate the destination view controller, another check on which table (search or normal) is displayed is needed
        if(sender == self.searchDisplayController.searchResultsTableView) {
            NSIndexPath *indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
            NSString *destinationTitle = [[filteredCandyArray objectAtIndex:[indexPath row]] name];
            [candyDetailViewController setTitle:destinationTitle];
        }
        else {
            NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
            NSString *destinationTitle = [[candyArray objectAtIndex:[indexPath row]] name];
            [candyDetailViewController setTitle:destinationTitle];
        }
 
    }
}

Open up the storyboard and make sure that the segue from the Candy Table View Controller to the Detail View has the identifier “candyDetail”. Compile and run the code at this point and see how the app now navigates to the Detail View from either the main table or the search table with ease.

Creating an Optional Scope Bar to Filter Results

If you wish to give your users another way to further filter their results, a Scope Bar can be used in conjunction with your search bar in order to filter out items by their category. The categories you will filter on are the ones you assigned to the Candy object when the candyArray was created: chocolate, hard, and other.

First, set up the scope bar on the storyboard. Go to the CandySearch View Controller and select the search bar. In the attributes inspector, check “Shows Scope Bar” in the Options section. Then modify the Scope Titles to be: “All”, “Chocolate”, “Hard” ,and “Other”. (You can use the + button to add more scope items and if you double-click an item, you can edit the item title). This is what your screen should look like:

Next, modify filterContentForSearchText: in CandyTableViewController.m to take the new scope into account. Replace the current method implementation with the following:

-(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
	// Update the filtered array based on the search text and scope.
    // Remove all objects from the filtered search array
	[self.filteredCandyArray removeAllObjects];
	// Filter the array using NSPredicate
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.name contains[c] %@",searchText];
    NSArray *tempArray = [candyArray filteredArrayUsingPredicate:predicate];
    if (![scope isEqualToString:@"All"]) {
        // Further filter the array with the scope
        NSPredicate *scopePredicate = [NSPredicate predicateWithFormat:@"SELF.category contains[c] %@",scope];
        tempArray = [tempArray filteredArrayUsingPredicate:scopePredicate];
    }
    filteredCandyArray = [NSMutableArray arrayWithArray:tempArray];
}

The new code introduces an additional NSPredicate — scopePredicate — that will further filter the array based on the scope. In order to support the “All” scope, you have to make sure that you don’t do any extra filtering if the scope is equal to “All”.

Compile and run the app. You’ll notice that the scope bar shows up — hey, that was easy! However, the app shows the scope bar before the user has even tapped on the Search Bar! It looks like we’re getting ahead of ourselves here. Add this code to the top of viewDidLoad (right after the call to super):

	// Don't show the scope bar or cancel button until editing begins
    [candySearchBar setShowsScopeBar:NO];
    [candySearchBar sizeToFit];

Compile and run now. Here’s how your scope bar should look:

Hiding the UISearchBar Like the Music App

It would be really neat if your app could initially hide the Search Bar, just like the way the Music app does. This initially gives your table view a little more real estate. Simply add the following code immediately below the code you just added to viewDidLoad:

    // Hide the search bar until user scrolls up
    CGRect newBounds = self.tableView.bounds;
    newBounds.origin.y = newBounds.origin.y + candySearchBar.bounds.size.height;
    self.tableView.bounds = newBounds;

Since your app hides the Search Bar, it wouldn’t be a bad idea to add a button to indicate to the user that a search function exists. The decision to include an explicit search button depends on the context of the app you’re developing, of course, but in this tutorial we’ll make it obvious that this app supports searching.

Begin by making an IBAction:

Add the follwing code to the bottom of CandyTableViewController.m:

-(IBAction)goToSearch:(id)sender {
    // If you're worried that your users might not catch on to the fact that a search bar is available if they scroll to reveal it, a search icon will help them
    // If you don't hide your search bar in your app, don’t include this, as it would be redundant
    [candySearchBar becomeFirstResponder];
}

Add the method definition to CandyTableViewController.h:

-(IBAction)goToSearch:(id)sender;

Now go to the storyboard and add a Bar Button Item to the navigation bar. In the Attributes Inspector, use Apple’s built-in search icon by changing the identifier to “search”. Then in the connections inspector, connect to goToSearch: by dragging from the “selector” item under “Sent Action” to the view controller.

Bingo! You now have a functional “Search” button on your navigation bar, which takes the user to the search interface. Compile and run to test…

and you’re done! Now give yourself a nice piece of candy :]

Where To Go From Here?

Here is a sample project with all of the code from the above tutorial.

Congratulations – you now have a working app that allows you to search directly from the main table view!

If you were going through this tutorial in order to learn how to implement search in your app, you’re in luck. The code that you’ve just worked through is completely extensible; all you have to do is add more objects as necessary. In a production app, the objects will not usually be defined directly in the code; they would be likely be loaded from some data source such as a plist file.

I hope to see you adding search capabilities to your table view apps in the future. If you have any questions or comments, please join the forum discussion below!

This is a post by iOS Tutorial Team Member Nicolas Martin, an independent iOS developer at nmappworks.

User Comments

88 Comments

[ 1 , 2 , 3 , 4 , 5 , 6 ]
  • First of all this is an amazing tutorial, thanks for taking the time out to make this accessible and practical to first time XCODE users.
    MY QUESTION: Instead of displaying the SCOPEBAR with the SEARCHBAR, would it be possible to arrange the Category in a tableview instead, and when a user clicks on a category, like "Hard", another tableview with all the HardArray comes up.
    In Summary can I link a Category Cell to a list of categories, then a Hard Cell to a list of Hard chocolate, rather than manually creating UITableViews and populating them.
    MikeAde
  • great article. However I found UISearchBar's Cancel and Clear buttons not working in iOS 7.
    here is a link for it:
    http://stackoverflow.com/questions/1916 ... 9#19841889

    also i posted the alternative solution underneath. Please feel free to post any other alternative solutions
    kiddo
  • great article, however i found the cancel button and clear button is not working in iOS7 if uisearchbar is hidden in the tableview

    http://stackoverflow.com/questions/1916 ... 9#19841889

    I also post the alternative solution underneath.
    kiddo
  • great article, however i found the cancel button and clear button is not working in iOS7 if uisearchbar is hidden in the tableview

    http://stackoverflow.com/questions/1916 ... 9#19841889

    I also post the alternative solution underneath.
    kiddo
  • Great article

    I have the same problem in iOS 7 than this article: http://stackoverflow.com/q/19245779/1827690
    Cancel button in search bar dont work in iOS 7 when search bar is initially hidden.
    mjimcua
  • Dear Nick,
    First: THX for this very helpful article!

    But I have the a problem with a memory leak. I use the search bar controller on my second "page". When i skip back (also without searching) i recieve a leak in instruments. :| :|

    I can repruduce this in "Candysearch": I put a ViewController before the scene, that is calling Candysearch: same leak, getting the output in the attachment :oops: :oops:

    I tried it with simulator an device development an release. Allways the same result...

    Can you help me???

    TIA!!!
    Ulli
  • This, as usual from this site, is an excellent tutorial. Thank you, Nicholas. As others noted, however, iOS 7 rendered its Cancel, clear (x), and scope controls unresponsive. Some of the other comments that address this topic did not do it for me, but I found a very similar sample direct from Apple at their site here:

    https://developer.apple.com/library/ios ... TS40007848

    It works as planned and similarly to the Candy tutorial. It also throws in state restoration for the search/table as well.
    ratzule
  • I still have the a problem with a memory leak. I use the search bar controller on my second ViewController. When i skip back (also without searching) i recieve a leak in instruments.
    Meanwhile i think, its a bug in UIKIT:

    I allways recieve a leak in instruments

    Leaked Object # Address Size Responsible Library Responsible Frame
    UIView 1 0xfe7d850 96 Bytes UIKit -[UITableView setTableHeaderBackgroundColor:]
    Malloc 144 Bytes 1 0xc4e2ca0 144 Bytes QuartzCore mem_alloc
    CALayer 1 0xfe77110 48 Bytes UIKit -[UIView _createLayerWithFrame:]
    Malloc 8 Bytes 1 0xaebe6f0 8 Bytes QuartzCore mem_alloc
    Malloc 16 Bytes 1 0xfcf7760 16 Bytes QuartzCore mem_alloc
    CGColor 1 0xfe77140 48 Bytes CoreGraphics CGTypeCreateInstance

    I have filed a bug report with Apple.

    Hi all, if you can reproduce the leak (just insert a ViewControler with a button with a Push to CandySearch and test it in instruments. If you can reproduce it, please join me and report the bug(?) to Apple...

    You may have a look at
    http://useyourloaf.com/blog/2012/09/06/ ... board.html

    Perhaps this leak concerns all, who is using the seachbar controller with scopes...

    TIA Ulli
    Ulli
  • I have problems with the Search Bar and Search Display I added a table view, but does not filter me, this is the code I am using, I appreciate if I can help.
    sleusson
  • Hi, thank you for the tutorial. Could you please suggest of how search result can be displayed using customised table cells (customised in storyboards under table view)? Thank you in advance.
    Ina
  • Henna is a dye plant used since ancient times. When it is applied on the skin, usually as a form of temporary art, as is done in India, Pakistan, Arab countries, and by expatriate communities from these areas, it is called Mehndi.
    mehndi designs for hands
    http://www.wallpapersbites.com/2013/11/ ... i-designs/
    whiteroses
  • Great tutorial! I've used it as a reference quite a few times! :D
    Mbyja
  • I have to point out my app crashes on this function: (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    The log says navigation subtree is corrupted. After debug, I think the sample function should change to sth. like this
    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"lincai: %@ *** %@ *** %d", tableView, self.searchDisplayController.searchResultsTableView, [indexPath row]);
    if (tableView == self.searchDisplayController.searchResultsTableView) {
    [self performSegueWithIdentifier:@"wordDetail" sender:tableView];
    }
    }
    reachlin
[ 1 , 2 , 3 , 4 , 5 , 6 ]

Other Items of Interest

Ray's Monthly Newsletter

Sign up to receive a monthly newsletter with my favorite dev links, and receive a free epic-length tutorial as a bonus!

Advertise with Us!

Our Books

Our Team

Tutorial Team

  • Kirill Muzykov

... 50 total!

Update Team

  • Ray Fix

... 15 total!

Editorial Team

  • Matt Galloway
  • Ryan Nystrom

... 23 total!

Code Team

  • Orta Therox

... 3 total!

Translation Team

  • Jose De La Roca
  • Team Tyran

... 33 total!

Subject Matter Experts

  • Richard Casey

... 4 total!