【问题标题】:NSFetchedResultsController not reloading data automaticallyNSFetchedResultsController 不会自动重新加载数据
【发布时间】:2014-07-17 11:39:47
【问题描述】:

我已经被一个错误困了几个小时了,希望有人能帮助我。

我有一个视图控制器,它使用 NSFetchedResultsController 加载数据(我正在使用核心数据),它获取我所有过去具有“日期”的对象,即日期

这是奇怪的部分...... 当应用程序来自后台时,我切换到“完整对象”选项卡并且它们不显示。但是,如果我立即关闭应用程序并重新启动它,一切看起来都很完美。如果我在应该重新加载时位于“完整对象”选项卡上,则会发生完全相同的事情,但如果在重新加载发生时我在另一个选项卡上并切换到它,这一切看起来都很完美。

据我所知,我的 NSFetchedResultsController 没有正确跟踪对托管对象上下文所做的更改。我确定这是我犯的一个简单错误,但我似乎找不到它!请帮忙。

- (void)viewDidLoad {
    [super viewDidLoad];

    // Setup table view
    self.tableView = [[UITableView alloc] init];
    self.tableView.separatorInset = UIEdgeInsetsZero;
    self.tableView.tableFooterView = [[UIView alloc] init];
    self.tableView.dataSource = self;
    self.tableView.delegate = self;
    self.tableView.backgroundColor = [UIColor clearColor];
    [self.view addSubview:self.tableView];

    NSError *error = nil;
    [self.fetchedResultsController performFetch:&error];
    if (error) {
        NSLog(@"Error: %@", error.localizedDescription);
    }
}

#pragma mark - NSFetchedResultsController section

- (NSFetchRequest *)myFetchRequest {
    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"DBTask"];
    fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES]];

    NSPredicate *datePredicate = [NSPredicate predicateWithFormat:@"taskDate < %@", [NSDate date]];
    NSPredicate *completePredicate = [NSPredicate predicateWithFormat:@"state == %d", DBTaskStateComplete];
    NSPredicate *latePredicate = [NSPredicate predicateWithFormat:@"state == %d", DBTaskStateLate];
    NSPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:[NSArray arrayWithObjects:datePredicate, completePredicate, latePredicate, nil]];

    [fetchRequest setPredicate:predicate];
    fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"taskDate" ascending:YES]];
    return fetchRequest;
}

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

    DBCoreDataStack *coreDataStack = [DBCoreDataStack defaultStack];
    NSFetchRequest *fetchRequest = [self myFetchRequest];
    _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:coreDataStack.managedObjectContext sectionNameKeyPath:@"sectionName"  cacheName:nil];
    _fetchedResultsController.delegate = self;
    return _fetchedResultsController;
}

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

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
    switch (type) {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        case NSFetchedResultsChangeDelete:
            [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        case NSFetchedResultsChangeUpdate:
            [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
    }
}

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
    switch (type) {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
    }
}

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

【问题讨论】:

  • 我们需要查看代码来帮助您找出错误。通常使用获取的结果控制器,顺便说一句,您不会根据通知重新加载,除非您使用它来更新获取参数。
  • 第一。使用 fetchresultscontrollers 时无需收听通知即可重新加载数据。这些控制器将监听其父托管对象上下文收到的通知,并在需要时进行更新。其次,发布您的委托并获取结果控制器初始化代码。
  • 哦,好吧,很高兴知道......我会发布我的代码。请注意,我正在使用 UIViewController 并将表视图添加为子视图。
  • 无论我做什么,NSFetchedResultsController 都不会响应托管对象上下文的变化。我想实现我在其他几十个应用中看到的,我缺少什么?
  • 只是检查:当您将新对象插入上下文时,表格视图是否更新?如果没有,您能否检查该对象是否存在于上下文中?而当你分析 fetched results controller 的 fetch request 时,对象在里面吗?你的类是否声明它符合 NSFetchedResultsControllerDelegate 协议?

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


【解决方案1】:

这里的问题是你的日期谓词中的日期[NSDate date]是在你的谓词初始化时生成的

该谓词不会主动跟踪 taskDate 与当前日期,而是与创建谓词的日期。

在此处使用获取的结果控制器委托可能不是实现此目的的最佳方式,您可以使用计时器,重置谓词并在每次计时器触发时执行新的获取。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-22
    • 2018-12-23
    • 1970-01-01
    相关资源
    最近更新 更多