cs193p – Assignment #6 Extra Task #4

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.

FacebooktwitterredditpinterestlinkedintumblrmailFacebooktwitterredditpinterestlinkedintumblrmail

Leave a Reply

Your email address will not be published.