NSFetchedResultsController,数据未更新

时间:2012-10-08 06:28:42

标签: iphone objective-c ios core-data 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. 

我通过修改同一个本地URL中的相同UIManagedDocument alloc来对其他类中的CoreData进行更改。

但是,我遇到了两个重要问题:

  • 更新数据库中的项目(例如更改产品名称或价格),但更改未反映在UI中,即我无法正确重新加载GMGridViewCell。 (注意与上面重新加载相关的代码)
  • 大部分时间,我在服务器中更新的产品都在数据库中重复,尽管我有一种机制可以防止出现这种错误。 (在创建产品之前,我首先使用唯一标识符搜索现有产品。如果有现有产品,我只需修改其详细信息)。这是代码:

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];
}

1 个答案:

答案 0 :(得分:1)

结果我必须听NSManagedObjectContextDidSaveNotification,我必须合并后台线程中修改的上下文中的更改和主线程中的更改。我从这个question

中选择的答案中得到了这个想法
[[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]; 
}