Search code examples
objective-ccore-dataios7nspredicate

Is it possible to change predicates from a UIButton?


I have a set of words in a Core Data model. I would like to have some buttons that filter based on category, like adjectives, verbs, etc.

I have code like below, but the table does not reload..

> - (IBAction)selectAdjectives:(id)sender {
>     NSLog(@"%s", __FUNCTION__);
>     predicateSwitch = 3; // an int
>     [NSFetchedResultsController deleteCacheWithName:nil];
>     [self.wordTable reloadData]; }
> 


> - (NSPredicate*)predicate {
>     NSLog(@"%s", __FUNCTION__);
>     NSPredicate *predicate = [[NSPredicate alloc] init];
>     switch (predicateSwitch) {
>         case 0:
>             predicate = nil;
>             break;
>         
>         case 1:
>             ...
>             break;
>             
>         case2:
>             ...
>             
>         case3:
>             predicate = [NSPredicate predicateWithFormat:@"SELF.category contains[c] %@",@"Adjective"];
>             break;
>             
> 
>         default:
>             predicate = [NSPredicate predicateWithFormat:@"SELF.category contains[c] %@",@"Noun"];
>             break;
>     }
>     NSLog(@"Predicate: %@", predicate);
>     
>     return predicate; }
> 


> - (NSFetchedResultsController *)fetchedResultsController {
>     //NSLog(@"%s", __FUNCTION__);
>     
>     if (_fetchedResultsController != nil) {
>         return _fetchedResultsController;
>     }
>     
>     NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
>     
>     NSEntityDescription *entity = [NSEntityDescription entityForName:@"WordEntity"
> inManagedObjectContext:self.managedObjectContext];
>     [fetchRequest setEntity:entity];
>     [fetchRequest setPredicate:[self predicate]];
>           // Create the sort descriptors array.    ...
>      
>     NSArray *sortDescriptors = @[sortDescriptor];
>     [fetchRequest setSortDescriptors:sortDescriptors];
>     
>     // Create and initialize the fetch results controller.
>     _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
> managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil
> cacheName:nil];
>     
>     _fetchedResultsController.delegate = self;
>     
>     return _fetchedResultsController; }


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    //NSLog(@"%s", __FUNCTION__);

    static NSString *CellIdentifier = @"WordCell";

    UITableViewCell *cell = (UITableViewCell *)[self.wordTable dequeueReusableCellWithIdentifier:CellIdentifier];

    // Configure the cell...
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    }

    WordEntity *word = nil;
    if (tableView == self.searchDisplayController.searchResultsTableView) {
        word = [self.searchResults objectAtIndex:indexPath.row];
        count = self.searchResults.count;
        self.numberWordsLabel.text = [NSString stringWithFormat:@"%lu", (unsigned long)count];

    } else {
        word = [self.fetchedResultsController objectAtIndexPath:indexPath];
        self.numberWordsLabel.text = [NSString stringWithFormat:@"%lu", (unsigned long)fullCount];
    }


        cell.textLabel.text =  .....;
        cell.detailTextLabel.text = .....;

I get the whole table, but the predicates are not firing, and the table view not reloaded. I'd appreciate any advice.


Solution

  • Several things wrong..

    1. See the switch statement. There is a missing space in cases 2 and 3.

    2. You can't just reload the table. You have to reload the view controller.. (I don't like this so I'm open to alternatives).

    3. You can't just reset the cache with

      [NSFetchedResultsController deleteCacheWithName:nil];

    you have to hammer it:

    self.fetchedResultsController = nil;
    

    So:

    - (IBAction)selectNouns:(id)sender {
        //NSLog(@"%s", __FUNCTION__);
        predicateSwitch = 1;
        self.fetchedResultsController = nil; 
        [self viewDidLoad];
    }