数据未更新的NSFetchedResultsController

我正在制作一个从服务器获取产品列表的应用程序。 然后我将它们存储在Core Data数据库中,并使用GMGridView呈现它们,数据源是NSFetchedResultsController 。 当我更改服务器中的产品详细信息时,我希望我的iOS应用程序同步并进行必要的更改,以便实现NSFetchedResultsControllerDelegate方法。 我应该如何正确更新我的gridView?

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { switch(type) { case NSFetchedResultsChangeInsert: [_currentData insertObject:anObject atIndex:newIndexPath.row]; [_currentData removeObjectAtIndex:indexPath.row]; [_gmGridView insertObjectAtIndex:newIndexPath.row animated:YES]; [_gmGridView removeObjectAtIndex:indexPath.row animated:YES]; [_gmGridView reloadObjectAtIndex:newIndexPath.row animated:YES]; [_gmGridView reloadObjectAtIndex:indexPath.row animated:YES]; [_gmGridView reloadData]; //[self updatePageControl]; break; case NSFetchedResultsChangeDelete: [_currentData removeObjectAtIndex:indexPath.row]; [_gmGridView removeObjectAtIndex:indexPath.row animated:YES]; //[self updatePageControl]; [_gmGridView reloadInputViews]; [_gmGridView reloadData]; break; case NSFetchedResultsChangeUpdate: [_gmGridView reloadObjectAtIndex:indexPath.row animated:YES]; ////////might be irrelevant, but just trying it out [_currentData insertObject:anObject atIndex:newIndexPath.row]; [_currentData removeObjectAtIndex:indexPath.row]; [_gmGridView insertObjectAtIndex:newIndexPath.row animated:YES]; [_gmGridView removeObjectAtIndex:indexPath.row animated:YES]; [_gmGridView reloadObjectAtIndex:newIndexPath.row animated:YES]; [_gmGridView reloadObjectAtIndex:indexPath.row animated:YES]; //////// [_gmGridView reloadInputViews]; [_gmGridView reloadData]; break; case NSFetchedResultsChangeMove: [_currentData removeObjectAtIndex:indexPath.row]; [_currentData insertObject:anObject atIndex:newIndexPath.row]; [_gmGridView removeObjectAtIndex:indexPath.row animated:YES]; [_gmGridView insertObjectAtIndex:newIndexPath.row animated:YES]; [_gmGridView reloadInputViews]; [_gmGridView reloadData]; break; } } 

一些细节:

 _currentData = [[self.fetchedResultsController fetchedObjects]mutableCopy]; //I did this because previously I wasn't using a fetchedResultsController but a NSMutableArray instead. I know that it's inefficient (because I have 2 models) but this is the simplest implementation I want to do now. 

我通过修改相同的UIManagedDocument分配,从同一本地URL初始化,使CoreData更改在一个不同的类。

但是,我有两个重要的问题:

  • 数据库中的项目被更新(例如,更改产品名称或价格),但更改不反映在UI中,即我无法正确地重新加载我的GMGridViewCell。 (注意上面重新加载的代码)
  • 大多数情况下,我在服务器上更新的产品在数据库中是重复的,尽pipe我有防止这种错误的机制。 (在创build产品之前,我首先使用唯一的标识符search现有的产品,如果有现有的产品,我只是修改其细节)。 代码如下:

 NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Product"]; request.predicate = [NSPredicate predicateWithFormat:@"product_id = %@", [imonggoInfo objectForKey:PRODUCT_ID]]; NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]; request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor]; NSError *error = nil; NSArray *matches = [context executeFetchRequest:request error:&error]; if (!matches | ([matches count] > 1)){ //handle error }else if ([matches count] == 0){ //make a new product }else{ //return existing item = [matches lastObject]; } 

原来我必须听NSManagedObjectContextDidSaveNotification ,我必须合并在后台线程和主线程中修改的上下文中的更改。 我从这个问题的答案中得到了这个想法

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextChanged:) name:NSManagedObjectContextDidSaveNotification object:nil]; 

//然后上下文中的更改必须合并

 - (void)contextDidSave:(NSNotification*)notification{ NSLog(@"contextDidSave Notification fired."); SEL selector = @selector(mergeChangesFromContextDidSaveNotification:); [self.itemDatabase.managedObjectContext performSelectorOnMainThread:selector withObject:notification waitUntilDone:NO]; }