Note that there are some explanatory texts on larger screens.

plurals
  1. PONSFetchedResultsController Delegate is removing and object from the results controller when I select a tableview row
    primarykey
    data
    text
    <p>Core Data Master-Detail Application. </p> <p>When my <code>tableView</code> loads it presents a view with <code>UIButtons</code> to select what category of items you want to view. The <code>IBAction</code> for the buttons takes that category and creates a <code>NSFetchedResultsController</code> with a <code>NSPredicate</code> based on that category. The only difference between the buttons is, 2 of the 8 buttons sets the <code>predicate</code> to grab all the objects based on a <code>BOOL</code>/<code>NSNumber</code> value that is set as a property on the object. The other 6 buttons grab all the objects based on their "category" which again is a <code>NSString</code> property set on the object </p> <p><strong>My Issue:</strong></p> <p>When I select any of the buttons that grab the objects by the category (<code>NSString</code>) everything works fine. It loads the tableview with all the correct objects I select a row the delegate method <code>-controller didChangeObject</code> is called with the type <code>NSFetchedResultsChangeUpdate</code> I pass in object to the <code>DetailViewController</code> and all is well.</p> <p>When I select any of the buttons that grab the objects by the <code>BOOL</code> value everything appears to work fine. The tableview loads all the correct objects and displays properly. <strong>However,</strong> when I select a row the delegate method <code>-controller didChangeObject</code> is called with the type <code>NSFetchedResultsChangeDelete</code> and my object is removed from the tableview. The <code>DetailViewController</code> is pushed on to the stack and displays all the information correctly.</p> <p>I don't know why it is removing my object from the fetched results, it makes no sense to me. Because there is nothing different that I am doing besides the fetch by <code>BOOL</code> property rather than the <code>NSString</code> property.</p> <p>Also; when I select a row I change a property value on the object in the <code>-tableview didSelectRowAtIndexPath</code>. The property I change is just a BOOL value to track if the item has been viewed or not yet. When I remove this line of code that changes this property value everything works fine. I don't understand why this line of code doesn't effect the other categories, only the category that grabs from the <code>BOOL</code> property.</p> <p><strong>CODE:</strong> <strong>IBAction for Categories buttons</strong></p> <pre><code>-(IBAction)goToPage:(id)sender { BOOL wishList = NO; BOOL cellar = NO; if ((UIButton*)sender == americanButton) { selectedCategory = @"american"; selectedSubCategory = nil; wishList = NO; cellar = NO; } else if ((UIButton*)sender == canadianButton) { selectedCategory = @"canadian"; selectedSubCategory = nil; wishList = NO; cellar = NO; } else if ((UIButton*)sender == irishButton) { selectedCategory = @"irish"; selectedSubCategory = nil; wishList = NO; cellar = NO; } else if ((UIButton*)sender == japaneseButton) { selectedCategory = @"japanese"; selectedSubCategory = nil; wishList = NO; cellar = NO; } else if ((UIButton*)sender == scottishButton) { selectedCategory = @"scotch"; selectedSubCategory = nil; wishList = NO; cellar = NO; } else if ((UIButton*)sender == verticalsButton) { selectedCategory = @"verticals"; selectedSubCategory = nil; wishList = NO; cellar = NO; } else if ((UIButton*)sender == otherButton) { selectedCategory = @"other"; selectedSubCategory = nil; wishList = NO; cellar = NO; } else if ((UIButton*)sender == wishListButton) { selectedSubCategory = @"wishlist"; selectedCategory = nil; wishList = YES; cellar = NO; } else if ((UIButton*)sender == cellarButton) { selectedSubCategory = @"cellar"; selectedCategory = nil; wishList = NO; cellar = YES; } if (wishList == YES) { [self fetchMyWhiskiesFromCategory:@"1" andResetFetchResultsController:YES withAttribute:@"wishlist"]; } else if (cellar == YES) { [self fetchMyWhiskiesFromCategory:@"1" andResetFetchResultsController:YES withAttribute:@"mycellar"]; } else { [self fetchMyWhiskiesFromCategory:selectedCategory andResetFetchResultsController:YES withAttribute:@"category"]; } } - (void)fetchMyWhiskiesFromCategory:(NSString *)category andResetFetchResultsController:(BOOL)reset withAttribute:(NSString *)attribute { NSError *error = nil; NSFetchedResultsController *resultsController = [self fetchedResultsControllerWithCategory:category andResetFetchResultsController:reset withAttribute:attribute]; if (![resultsController performFetch:&amp;error]) { NSLog(@"Error! %@", error); } } - (NSFetchedResultsController *)fetchedResultsControllerWithCategory:(NSString *)category andResetFetchResultsController:(BOOL)reset withAttribute:(NSString *)attribute { if (reset == YES) { // If asking for new results controller with new category NSLog(@"Reset results"); self.fetchedResultsController = nil; _fetchedResultsController = nil; } if (_fetchedResultsController != nil) { //NSLog(@"returned Old Controller"); return _fetchedResultsController; } NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init]; //Entity NSEntityDescription *entity = [NSEntityDescription entityForName:@"Whisky" inManagedObjectContext:[self managedObjectContext]]; [fetchRequest setEntity:entity]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@",attribute, category]; [fetchRequest setPredicate:predicate]; //Sort all entities by name property (whisky name) NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name"ascending:YES]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; [fetchRequest setSortDescriptors:sortDescriptors]; //Create FetchedResultsController organizing by sections of first letter of name _fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"name.stringGroupByFirstInitial" cacheName:nil]; //name.stringGroupByFirstInitial _fetchedResultsController.delegate = self; return _fetchedResultsController; } </code></pre> <p><strong>didSelectRow</strong></p> <pre><code>- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { if (!self.detailViewController) { self.detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil]; } Whisky *whisky = [self.fetchedResultsController objectAtIndexPath:indexPath]; [whisky setIsNew:[NSNumber numberWithBool:NO]]; self.detailViewController.managedObjectContext = self.managedObjectContext; self.detailViewController.whisky = whisky; [self.navigationController pushViewController:self.detailViewController animated:YES]; } </code></pre> <p><strong>NSFetchedResultsController Delegates</strong></p> <pre><code>- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { [self.tableView beginUpdates]; } - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id &lt;NSFetchedResultsSectionInfo&gt;)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { switch(type) { case NSFetchedResultsChangeInsert: [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; NSLog(@"didChangeSection - ChangeInsert"); break; case NSFetchedResultsChangeDelete: [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; NSLog(@"didChangeSection - ChangeDelete"); break; } } - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { UITableView *tableView = self.tableView; switch(type) { case NSFetchedResultsChangeInsert: [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; NSLog(@"didChangeObject - ChangeInsert"); break; case NSFetchedResultsChangeDelete: [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; NSLog(@"didChangeObject - ChangeDelete"); break; case NSFetchedResultsChangeUpdate: [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; NSLog(@"didChangeObject - ChangeUpdate"); break; case NSFetchedResultsChangeMove: [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; NSLog(@"didChangeObject - ChangeMove"); break; } } - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { [self.tableView endUpdates]; } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload