Please note, this blog entry is from a previous course. You might want to check out the current one.
Make one or more of your table views searchable. Check out UISearchDisplayController and UISearchBar.
Add a bar button to enable the search functionality in code and initialize it lazily:
@property (nonatomic, strong) IBOutlet UIBarButtonItem *searchButton;
...
- (UIBarButtonItem *)searchButton
{
if (!_searchButton) {
_searchButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSearch
target:self
action:@selector(searchButtonPressed:)];
}
return _searchButton;
}
- (void)viewDidLoad
{
...
self.navigationItem.rightBarButtonItem = self.searchButton;
}
When the search button gets pressed, show the search bar and activate it (making it first responder), or hide it if the button gets pressed again:
- (IBAction)searchButtonPressed:(id)sender
{
if (self.tableView.tableHeaderView) {
self.tableView.tableHeaderView = nil;
} else {
self.tableView.tableHeaderView = self.searchBar;
if (self.searchPredicate) {
self.searchPredicate = nil;
[self setupFetchedResultsController];
}
[self.searchBar becomeFirstResponder];
}
}
The search bar is initialized lazily, defining the class also as delegate for the search functionality:
@interface FlickrPhotoTagTVC () <UISearchBarDelegate>
...
@property (nonatomic, strong) UISearchBar *searchBar;
...
- (UISearchBar *)searchBar {
if (!_searchBar) {
_searchBar = [[UISearchBar alloc]
initWithFrame:self.navigationController.navigationBar.frame];
self.searchBar.delegate = self;
}
return _searchBar;
}
When the text of the search bar changes, change the predicate for the fetched-results controller. When the search is “finished”, hide the search bar.
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
if ([searchText length]) {
self.searchPredicate = [NSPredicate predicateWithFormat:@"name contains[cd] %@", searchText];
} else {
self.searchPredicate = nil;
}
[self setupFetchedResultsController];
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
self.tableView.tableHeaderView = nil;
}
To let the fetched-results controller know, that it should actually “search” something use an additional property:
@property (nonatomic, strong) NSPredicate *searchPredicate;
...
- (void)setupFetchedResultsController
{
...
request.predicate = self.searchPredicate;
...
}
Follow those steps for the photo-table-view controller. The only difference here is that, this controller already has a predicate which needs to be combined with the search predicate:
- (void)setupFetchedResultsController
{
...
if (self.searchPredicate) {
request.predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[request.predicate, self.searchPredicate]];
}
...
}
For the recent-photos-table-view controller, just make the search-predicate property from the previous table public (so you do not have to redefine it again), and adjust the setup of the fetched-results controller.
The complete code is available on github.