0

Hi I am trying to implement a search bar function for a table view using core data and NSFetchedResults Controller.

Quite a number of answers on SO suggest using a predicate for search using something like the following code:

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
    if ([searchText length] == 0) {
        _fetchedResultsController = nil;
    }
    else {
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name contains[cd] %@", searchText];
        [[_fetchedResultsController fetchRequest] setPredicate:predicate];
        [[_fetchedResultsController fetchRequest] setFetchLimit:50];
    }

    NSError *error;
    if (![[self fetchedResultsController] performFetch:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    }

    [[self tableView] reloadData];
}

I have also tried variations of this. In every case, however, I'm having the same problem.

First, when you search, it says no results. Also if you type in a few letters and hit the x, you get a grayed out screen and if you click again, you get the normal table view.

However, after typing in a letter and seeing "No Results" if you click cancel you get the results you should have gotten. Once that happens you cannot get back to the full tableview without rebuilding the project.

The only idea I have so far is it might have something to do with _fetchedResultsController vs fetchedResultsController (the property in this source file is ftchedResultsController without the underscore) but changing those only throws error messages.

Thank you for any suggestions on what could be causing this.

user1904273
  • 4,562
  • 11
  • 45
  • 96

1 Answers1

1

You have two table views, one from the search and the main one from the main table. You should disable the search controller's table view if you want to keep showing your main table view with the filter implied by the search.

self.searchResultsController.active = NO;

You could set this every time the search bar would otherwise set this to YES, like in textDidChange. In your FRC getter, you check for any string in the search bar and add a predicate if necessary. In textDidChange you nil out the FRC and reloadData. That's it.

Mundi
  • 79,884
  • 17
  • 117
  • 140
  • Where would that go? I tried it after _fetchedResultsController = nil; and got same result. – user1904273 Apr 18 '15 at 22:30
  • It should always be disabled. If you do not want to use the search display controller, you could replace the search bar with a UITextField altogether. - Also, if you set FRC to nil and it is created lazily, it is enough to simply call `reloadData`. The search bar logic should be in your FRC creation code. – Mundi Apr 18 '15 at 22:32
  • Sorry to be dense but where should I put above line of code? In viewdidload? Tried it in viewdidload and viewwillappear without success. – user1904273 Apr 18 '15 at 22:36
  • Are you suggesting I get rid of the searchbar method and put the if ([searchText length] == 0) { _fetchedResultsController = nil; } logic in the FRC method? – user1904273 Apr 18 '15 at 23:20
  • I added some more explanations. It seems the originally posted method is deprecated since iOS 8. – Mundi Apr 19 '15 at 09:40
  • Ok. I almost got it. I put your line above (with the old searchDisplayController since that is what is in storyboard) in the search bar method before reloading. To make the full table reload upon hitting cancel button, I added a - (void)searchBarCancelButtonClicked: method and called a reload in there. However the cancel button does not appear until you click a second time in the search bar. Is there a way to force a reload when you just click outside the search box or something? Or what is preferred way to exit the search results and go back to full table? – user1904273 Apr 19 '15 at 19:26