【问题标题】:Row not moving when changing the model with NSFetchResultsController使用 NSFetchResultsController 更改模型时行不移动
【发布时间】:2012-12-22 07:45:52
【问题描述】:

我正在这里开发我的第一个 iPhone 应用程序(一个基本的待办事项列表应用程序),并且刚刚将 NSFetchResultsController 添加到我的表格视图中。我有 2 行部分,添加行没有问题,它们按目标的已完成属性是否为 true 进行排序 - 如果是,则进入底部并被划掉。

并且每当您在顶部的一行上向右滑动时,它会将目标的 complete 属性更改为 true 并将其移动到底部:

  RegimenGoal *goal = [_fetchedResultsController objectAtIndexPath:swipedIndexPath];
  goal.completed = [NSNumber numberWithBool:YES];

  [context save:&error];

这是我的view controller code

出于某种原因,这仅适用于我刚刚创建的目标,但不适用于我添加的现有目标。经过一些调试,我意识到 NSFetchedResultsChangeMove 并没有被触发,而是 NSFetchedResultsChangeUpdate 是每当我对不是新的现有目标执行此操作时。

在 Apple 文档"Moved Objects Sometimes Reported as Updated" 上也遇到过这个问题。我通过简单地检查完成的属性是否为真来尝试了那里列出的解决方法。

当我这样做时,我发现 newIndexPath 不是新的——它只是旧的 indexPath,这让我很困惑……知道为什么会这样吗?

【问题讨论】:

    标签: iphone ios uitableview core-data nsfetchedresultscontroller


    【解决方案1】:

    在创建获取的结果控制器时出错。如果您通过指定 sectionNameKeyPath:@"completed" 将结果分组到多个部分,那么您必须使用相同的键添加第一个排序描述符:

    NSSortDescriptor *completeSort = [[NSSortDescriptor alloc] initWithKey:@"completed" ascending:YES];
    NSSortDescriptor *daySort = [[NSSortDescriptor alloc] initWithKey:@"dateCreated" ascending:YES];
    [dayRequest setSortDescriptors:[NSArray arrayWithObjects:completeSort, daySort, nil]];
    

    另一个问题在tableView:cellForRowAtIndexPath:

    [self configureCell:cell atIndexPath:indexPath];
    [cell formatCell:indexPath.section];
    

    这里假设第 0 部分包含所有带有 completed = NO 的项目,而第 1 部分包含所有带有 completed = YES 的项目。但如果所有项目都完成了,那么只有一个部分(第 0 部分)包含所有已完成的项目。所以你不能使用indexPath.section 作为formatCell 的参数。您应该改用goal.completed 的值。例如,您可以将formatCell 调用移动到configureCell:atIndexPath: 方法中:

    - (void)configureCell:(RegimenCell *)cell atIndexPath:(NSIndexPath *)indexPath {
        RegimenGoal *goal = [self.fetchedResultsController objectAtIndexPath:indexPath];
        cell.label.text = goal.text;
        [cell formatCell:goal.completed.intValue];
    }
    

    现在让表格单元格reuseIdentifier 依赖于节和行号没有多大意义。我认为您可以替换

    NSString *CellIdentifier = [NSString stringWithFormat:@"%d-%d", indexPath.row, indexPath.section];
    

    通过固定字符串

    NSString *CellIdentifier = @"YourCellIdentifer";
    

    setNavTitle 方法中也存在类似问题:

    int goalsCount = [_tableView numberOfRowsInSection:0];
    int completedCount = [_tableView numberOfRowsInSection:1];
    

    同样,如果所有目标都已完成,则它们都在第 0 节中,并且没有第 1 节。在这种情况下,您当前的代码将显示“(0%)”而不是“(100%)”。

    补充说明:

    • “移动的对象有时报告为已更新”解决方法在这里似乎没有必要。
    • 对于NSFetchedResultsChangeUpdate 事件,您可以调用[self configureCell:...][[_tableView reloadRowsAtIndexPaths:...]。无需调用两者。
    • 实例变量_fetchedResultsController 只能在fetchedResultsController 方法中使用,该方法根据需要创建获取结果控制器(FRC)。在所有其他地方,您应该使用self.fetchedResultsController 以确保在必要时创建 FRC。

    【讨论】:

    • 非常感谢,马丁!我很感激。我不知道我也必须在排序描述符中包含完整,而且您对单元格格式和导航标题是正确的。对于我的重用标识符,我仍然需要以某种方式按行/部分标记它,以便我正在查看的删除标签,所以我改为通过目标完成。
    猜你喜欢
    • 1970-01-01
    • 2021-06-24
    • 1970-01-01
    • 2017-10-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-26
    • 2016-07-18
    • 1970-01-01
    相关资源
    最近更新 更多