NSfetchedResultsController更改不反映到UI

时间:2017-10-16 08:36:24

标签: ios objective-c uitableview core-data nsfetchedresultscontroller

NSFetchedResultsController的问题在于我获取了数据,并且UITableViewcacheName设置为nil。稍后当我更改predicate NSFetchedResultsController并调用perfromFetch时,它不会刷新UITableView,但NSFetchedResultsController内的数据会更新。还有一点,NSFetchedResultsControllerDelegate方法也没有调用。

先谢谢。

已编辑:已添加代码

NSFetchedResultsControllerDelegate

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

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

    UITableView *tableView = self.tableView;

    switch(type) {

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

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

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

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

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

    switch(type) {

        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;

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

        case NSFetchedResultsChangeMove:
        case NSFetchedResultsChangeUpdate:
            break;
    }
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView endUpdates];
}

NSFetchedResultsController

- (NSFetchedResultsController *)fetchedResultsController
{
    if (_fetchedResultsController) {
        return _fetchedResultsController;
    }

    NSManagedObjectContext *context = [GmailDBService sharedService].managedObjectContext;
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Thread"];
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"historyId" ascending:NO];
    fetchRequest.predicate = [NSPredicate predicateWithFormat:@"SUBQUERY(messages, $m, ANY $m.labels.identifier == %@).@count > 0", self.label.identifier];
    fetchRequest.sortDescriptors = @[sortDescriptor];
    fetchRequest.fetchBatchSize = 20;

    _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
    _fetchedResultsController.delegate = self;
    [_fetchedResultsController performFetch:nil];

    return _fetchedResultsController;
}

谓词刷新

- (IBAction)unwindToThreadsController:(UIStoryboardSegue *)segue
{
    self.fetchedResultsController.fetchRequest.predicate = [NSPredicate predicateWithFormat:@"identifier == %@", @"15f1919682399cc9"];
    [self.fetchedResultsController performFetch:nil];
}

1 个答案:

答案 0 :(得分:0)

fetchedResultsController并不昂贵。你不应该根据需要创建和销毁它们。当您需要更改谓词时,丢弃当前的fetchedResultsController并创建一个新的谓词。在你这样做之后不要忘记重新加载tableView。

这些更改不会触发fetchedResultsController,因为您正在监视线程,但您的谓词基于消息。因此,当消息更改时,它不会触发fetchedResultsController中的更改。控制器仅监视对一个实体的更改,并且不希望更改其他实体来实现它。您可以通过以下几种方式解决此问题:1)设置fetchedResultsController以查看消息并按线程对它们进行分组,然后仅将每个部分(即线程)显示为一行。 2)每次更改消息时也更改其线程(对于fetchedResultsController而言,message.thread.threadId = message.thread.threadId将计为更改)。

此外,console.log(`Current directory: ${process.cwd()}`); // C:\Users\dbauszus\Documents\GitHub\maps (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.setContent(jsr.templates('./views/report.html').render(), {waitUntil: 'load'}); // works with an url to the same file. // await page.addScriptTag('http://localhost:3000/maps/js/build/report_bundle.js'); // path for js file on windows C:\Users\dbauszus\Documents\GitHub\maps\public\js\build\report_bundle.js await page.addScriptTag({path: 'public\\js\\build\\report_bundle.js'}); await page.screenshot({path: 'example.png'}); await browser.close(); })(); 并未受到fetchedResultsController的尊重,因此您应将其删除以便清楚。