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.