Core data object in UITableview disappears when updating object

I have this weird problem related to updating my NSManagedObject. When I try to update one of its attributes in disappears in the UITableview where its is presented and only disappears again when I refetch from Core data. I think this is caused by how I fetch the content of my entity in another thread like so:

[[[DataManager sharedInstance] backgroundManagedObjectContext] performBlock:^{

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    fetchRequest.entity = [NSEntityDescription entityForName:@"Ret" inManagedObjectContext:[[DataManager sharedInstance] backgroundManagedObjectContext]];

    fetchRequest.predicate = [NSPredicate predicateWithFormat:@"menu.name == %@ ", self.menu.name];

    fetchRequest.resultType = NSManagedObjectIDResultType;

    NSArray *results =  [[[DataManager sharedInstance] backgroundManagedObjectContext] executeFetchRequest:fetchRequest error:nil];




    NSLog(@"%@", [NSThread currentThread]);
    dispatch_async(dispatch_get_main_queue(), ^{


        [self loadWithObjectIDs:results];
        [_theTableview reloadData];



    });


}];

This is fired in the viewDidAppear method.

And then my NSFetchResultsController method to update the UI on the main thread:

-(void)loadWithObjectIDs:(NSArray *)objectsIDs {





    _theManagedObjectContext = [[DataManager sharedInstance] mainManagedObjectContext];



    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    fetchRequest.entity = [NSEntityDescription entityForName:@"Ret" inManagedObjectContext:_theManagedObjectContext];


   fetchRequest.predicate = [NSPredicate predicateWithFormat:@"SELF IN %@ ", objectsIDs];


    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
    fetchRequest.sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];

    [NSFetchedResultsController deleteCacheWithName:@"dishes"];
    self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_theManagedObjectContext sectionNameKeyPath:nil cacheName:@"dishes"];
    _fetchedResultsController.delegate = self;


    NSError *error = nil;   


    if (![_fetchedResultsController performFetch:&error]) {
        NSLog(@"Fetch Failed");

    }


    NSArray *contentsOfFetch = _fetchedResultsController.fetchedObjects;



}

Then in another method connected to a button in my UITableViewCell, where I update an attribute of my NSMangedObject:

-(void)addTC:(UIButton *)sender {

   //sender.tag equals indexPath.row
   NSIndexPath *ip = [NSIndexPath indexPathForRow:sender.tag inSection:0];



    Ret *ret = (Ret*)[_fetchedResultsController objectAtIndexPath:ip];

   //The Cell disappears if I use this code to update my attribute. 

   NSInteger amountToUpdate = ret.amount.intValue;
    amountToUpdate++;
    ret.amount = [NSNumber numberWithInt:amount];

    /*Method to Save Main Context: includes:  
    NSError *error = nil;
    if (![context save:&error]) {

    }*/

    [self saveCurrentContext:_theManagedObjectContext];

  }

How would I manage to fix this little problem, so the NSManagedObject does not disappear, in my UITableview, when I update its attribute?

Upvotes: 1

Views: 720

Answers (1)

Martin R
Martin R

Reputation: 539745

I don't see any advantage in using a fetched results controller (FRC) as table view data source in your setup. A FRC is useful for change tracking with automatic update of the table view. But that does not apply here, because the actual fetch is done on a background thread and the fetched objects are passed (via object id) to the main thread.

There might also be the problem, if a managed object id is a temporary id. If the object is saved, the id changes (becoming a permanent id). That could explain why the object is disappearing from the table view.

So one thing you could try is to call obtainPermanentIDsForObjects: for all objects in the background thread before passing the ids to the main thread.

Alternatively, you can just execute a simple fetch

self.dataSourceArray = [_theManagedObjectContext executeFetchRequest:fetchRequest error:&error];
[self.tableView reloadData];

and use this array as table view data source. In this case, if you modify objects, you would have to call reload/insert/deleteRowsAtIndexPaths if necessary.

Upvotes: 1

Related Questions