开发者

UITableView not updating DataSource after change to NSFetchedResultsController

开发者 https://www.devze.com 2023-01-07 10:29 出处:网络
I have an UITableView populated by a NSFetchedResultsController. The initial fetch works fine. I can add, remove, modify, etc with zero problems.. But I want to add user-defined sorting to the table.

I have an UITableView populated by a NSFetchedResultsController. The initial fetch works fine. I can add, remove, modify, etc with zero problems.. But I want to add user-defined sorting to the table. I am doing this by changing the NSFetchedResultsController to use a different sortDescriptor set, and a different sectionNameKeyPath. Here is the code where I change the fetch:

-(void)changeFetchData {
    fetchedResultsController = nil;

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Object" inManagedObjectContext:managedObjectContext];
    [fetchRequest setEntity:entity];

    NSString *sortKey = @"sortKey";
    NSString *cacheName = @"myNewCache";
    BOOL ascending = YES;

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:ascending];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [fetchRequest setSortDescriptors:sortDescriptors];

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:sortKey cacheName:nil];
    self.fetchedResultsController = aFetchedResultsController;
    fetchedResultsController.delegate = self;

    [aFetchedResultsController release];
    [fetchRequest release];
    [sortDescriptor release];
    [sortDescriptors release];

    NSError *error;
    if (![[self fetchedResultsController] performFetch:&error]) {
        // Update to handle the error appropriately.
        NSLog(@"Fetch failed");
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);  // Fail
    }

    [self.tableView reloadData];
}

When I call this method, it works great. The table immediately re-orders itself to use the new section info, and the new sorting parameters. But if I add or remove items to the data, the TableView doesn't update its info, causing a crash. I can NSLog the count of the total number of objects in the fetchedResultsController, and see it increase (and decrease) but if I NSLog the return values for numberOfRowsInSection to monitor a change there, the method gets called, but the values don't change. The get the following crash (for addition, but the deletion one is similar)

Invalid update: invalid number of rows in section 2. The number of rows contained in an existing sec开发者_JS百科tion after the update (3) must be equal to the number of rows contained in that section before the update (3), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted). with userInfo (null)

If I restart the app, I see the added item, or do not see the deleted item, so I am modifying the datasource correctly.

Any ideas?


It's possible that the old controller is still alive. If so, it might still be calling the tableview controller as its delegate and activating the table update using it's own data.

I would suggest logging the fetched results controller object in numberOfRowsInSection to confirm that it using the new controller. You should set the old controller's delegate to nil before assigning the new one.


On one occasion, adding:

- (void)viewDidDisappear:(BOOL)animated
{     
 self.fetchedResultsController.delegate = nil;
}

Solved a similar issue which arises when number of rows changes but data held is still different and not up-to-date.

0

精彩评论

暂无评论...
验证码 换一张
取 消