NSFetchedResultsController不更改实体更新的排序顺序;确实更新而不是移动

时间:2017-07-30 23:12:30

标签: ios core-data nsfetchedresultscontroller nssortdescriptor

我的iOS应用有一个视图控制器,可显示收件箱项目列表。这些收件箱项是核心数据数据库中的实体,列表由NSFetchedResultsController使用主线程托管上下文(NSMainQueueConcurrencyType)在视图控制器中管理。

NSFetchedResultsController之外,对实体的所有访问仅限于在具有私有上下文的专用GCD调度队列上运行的代码。因此,在实体中设置属性值以及读取这些实体属性值会在此专用GCD队列和上下文中发生。

具有NSFetchedResultsController的视图控制器监视主线程上下文中的更改。变更发生在专用队列和上下文的后台。代码监视NSManagedObjectContextDidSaveNotification通知,当后台线程更新属性值时,这些更改将被推送到主线程上下文中。

NSFetchedResultsController设置为对两个排序描述符进行排序,即“sortScore”和“date”(其中只有一个正在更新,“date”,因此每个托管对象实例都具有相同的“sortScore”做它不会影响排序。)

当“日期”更改发生时,NSFetchedResultsController会通知它并发布更改,但会将其发布为“更新”而不是“移动”,因此排序不会发生变化基于排序描述符和更新的“日期”,新值应该落在排序的其他地方。

我不知疲倦,经过几个小时的工作并跟踪NSManagedObjectContextDidSaveNotification和其他可能出现问题的点,以及为什么取出的结果控制器发送“更新”更改而不是“移动” “改变。

此应用程序使用较旧的分叉版Robbie Hanson XMPPFramework来管理核心数据,以备不熟悉。

(为了解决这个问题,昨晚一旦DID正常工作,并且一次又一次地进行了移动。我已经删除了应用程序并从全新安装开始,它开始工作。但后续运行无效并删除了应用程序开始新鲜没有解决它,以便开始新鲜的效果可能是巧合。)

我已经使用了日志记录和断点来显示获取的结果控制器正在发送“更新”而不是“移动”。

这是代码。

在视图控制器的init内部调用此创建方法,设置并执行NSFetchedResultsController的初始设置。

@property  (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;

- (NSFetchedResultsController *)createFetchedResultsControllerUsingStorage:(XMPPCoreDataStorage *)storage entityName:(NSString *)entityName
{
    NSManagedObjectContext *context = [storage mainThreadManagedObjectContext];
    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:entityName];

    NSSortDescriptor *sortDescriptorScore = [[NSSortDescriptor alloc] initWithKey:@"sortScore" ascending:NO];
    NSSortDescriptor *sortDescriptorDate = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptorScore, sortDescriptorDate, nil];
    [fetchRequest setSortDescriptors:sortDescriptors];

    NSFetchedResultsController *controller = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];

    [controller setDelegate:self];

    [self updateResultsDataSetForController:controller];

    return controller;
}

- (BOOL)updateResultsDataSetForController:(NSFetchedResultsController *)controller
{
    NSError *error;
    BOOL success = [controller performFetch:&error];

    if (nil != error) {
        NSLog(@"Error fetching inbox items for the inbox view controller.  Error = %@", error);
    }

    return success;
}

处理NSFetchedResultsControllerDelegate中的更改的代码基本上是从Apple文档中复制和粘贴的

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
    [self.conversationsTable beginUpdates];
}


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
    atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{

    switch(type) {
        case NSFetchedResultsChangeInsert:
            [self.conversationsTable insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                            withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.conversationsTable deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                             withRowAnimation:UITableViewRowAnimationFade];
            break;

        default:
            break;
    }
}


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
    atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
    newIndexPath:(NSIndexPath *)newIndexPath
{

    UITableView *tableView = self.conversationsTable;

    switch(type) {

        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                       withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                       withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate: {
            MyAppInboxCell *cell = [tableView cellForRowAtIndexPath:indexPath];
            MyAppXMPPInboxBaseMember *inboxItem = [self.fetchedResultsController objectAtIndexPath:indexPath];

            MyAppConversation *conversation = [inboxItem conversation];
            [cell configureCell:conversation];
            }
            break;


        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                       withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                       withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}

0 个答案:

没有答案