Well you're on the right track... it is exactly to do with the connection of your controller class to your controller xib.
When you want to initialise a Search Bar and Search Display Controller into a UITableView, you are effectively adding a second table view that, when activated, must be managed by code in your UITableViewController
class in the same manner as any UITableView
.
I have used these SO questions/answers to check my own answer - I recommend you take a look:
I have read the Apple Documentation. I recommend you do the same to help you understand this.
First Step:
You will need to set data source and delegate methods for both table views when you run your controller class.
Before you do any of this, include this property...
@property (nonatomic, strong) UISearchDisplayController *searchController;
The following code describes how to initialise and set the appropriate properties for a UISearchBar
and a UISearchDisplayController
. If you are programmatically creating a UITableViewController
in code you will also need to set the data source and delegate for it (not shown to keep the code easy to read).
You have two options here - which one you choose depends on your code and what you wish to achieve - either set these in your init
/awakeFromNib
methods, or set these in one of your table view controller (TVC) lifecycle methods.
Option One - Init
(Note1: Paul Hegarty's extraordinary iTunesU lectures taught me to init/awake a class as follows - in this way you are covered for both scenarios - you call init or it can awakeFromNib.)
- (void)setup {
// Provide initialisation code here!!!
UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectZero];
[searchBar sizeToFit];
[searchBar setDelegate:self];
[self setSearchController:[[UISearchDisplayController alloc] initWithSearchBar:searchBar
contentsController:self]];
[self.searchController setSearchResultsDataSource:self];
[self.searchController setSearchResultsDelegate:self];
[self.searchController setDelegate:self];
}
- (void)awakeFromNib {
[self setup];
}
- (id)initWithStyle:(UITableViewStyle)style {
self = [super initWithStyle:style];
if (self) {
[self setup];
}
return self;
}
OR
Option Two - TVC Lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectZero];
[searchBar sizeToFit];
[searchBar setDelegate:self];
[self setSearchController:[[UISearchDisplayController alloc] initWithSearchBar:searchBar
contentsController:self]];
[self.searchController setSearchResultsDataSource:self];
[self.searchController setSearchResultsDelegate:self];
[self.searchController setDelegate:self];
[self.tableView setTableHeaderView:self.searchController.searchBar]; // see Note2
...< other code as required >...
}
Note2: Regardless of which of these options you choose, you will need to place the following line of code in your viewDidLoad
method...
[self.tableView setTableHeaderView:self.searchController.searchBar]; // (or just searchBar)
Second Step:
Notes:
The table view that represents your complete data set (OldList
) can be called using self.tableView
(PS convention is to start each variable with lower case - so change your property name from OldList
to oldList
).
The table view that represents the filtered data set (filteredList) can be called using self.searchController.searchResultsTableView
.
While you have prepared your tableView:cellForRowAtIndexPath:
data source method, I suspect you have other data source (and maybe delegate) methods that need to be informed of which table view is the current table view, before they are able to function properly and provide you with a fully operational search results table view and search function.
For example:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (tableView == self.searchController.searchResultsTableView)
return 1;
return [[self.oldList sections] count];;
}
and:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == self.searchController.searchResultsTableView)
return [self.filteredList count];
return [self.oldList count];
}
Note that there may be other data source (and maybe delegate) methods that need to be informed of which table view is the current table view... I will leave it to you to determine which of these methods are to be modified, and the corresponding code necessary to adjust the table view.
Third Step:
You will be required to register a nib and reuse identifier for your search results table view.
I prefer to create a separate nib file (called "TableViewCellSearch.xib") that contains one table view cell, with the reuse identifier "SearchCell", and then place the code to register this nib and reuse identifier in the following UISearchDisplayController
delegate method.
It is worth noting that this code is just as effective after the code block examples above in init
/awakeFromNib
/viewDidLoad
.
- (void)searchDisplayController:(UISearchDisplayController *)controller willShowSearchResultsTableView:(UITableView *)tableView {
static NSString *cellIdentifierSearch = @"SearchCell";
UINib *nib = [UINib nibWithNibName:@"TableViewCellSearch" bundle:nil];
[self.searchController.searchResultsTableView registerNib:nib forCellReuseIdentifier:cellIdentifierSearch];
}
Try these suggestions.
Hope this helps.