为啥 NSFetchedResultsController 不能正确加载章节标题?

Posted

技术标签:

【中文标题】为啥 NSFetchedResultsController 不能正确加载章节标题?【英文标题】:Why is NSFetchedResultsController not correctly loading section titles?为什么 NSFetchedResultsController 不能正确加载章节标题? 【发布时间】:2010-01-24 22:46:22 【问题描述】:

我正在使用 NSFetchedResultsController 和 UITableViewController。

我在我的核心数据模型中创建了一个瞬态字段,用作 UITableView 部分的标签。该字段的名称是“sectionIndex”。在我的应用程序中,“客户”实体有许多“工作”(一对多) - 所以我检索工作的查询(通过部分)按关联的“客户”名称对它们进行分组。

我已在我的代码库中将此方法实现为“工作”实体上的类别。

@implementation Job (TransientMethods)

- (NSString*)sectionIndex 
    NSLog(@"JobWrapper.Job.sectionIndex: %@", self.client.name);
    return self.client.name;


@end

字符串“sectionIndex”作为 sectionNameKeyPath 参数传递给 NSFetchedResultsController 的 init 方法。

如果我从模拟器中删除应用程序 - 那么应用程序第一次运行时,Jobs 的首页会按照此处列出的 sectionIndex 方法正确检索 Jobs 并按 Job 的 Client.name 对 Jobs 分组。在日志中,我确实可以看到这个 sectionIndex 方法被多次调用。

但是,应用程序的后续运行不会调用 sectionIndex 方法......但是,部分标签仍会显示上次运行的值。这是怎么回事?运行之间是否有一些神奇的缓存?

这种行为会导致更大的问题。在查看 UITableView 时,如果我使用稍微不同的谓词释放和分配 NSFetchedResultsController,并且如果结果集是 SAME SIZE,......那么这些相同的原始部分名称将显示在所有新结果中!

当然,没有新的日志条目。这意味着永远不会查找列,这意味着代码永远不会调用或查找瞬态字段。好像这些字段没有故障。

现在,如果备用查询返回不同数量的结果,则将加载部分名称。 IE:在这种情况下,日志会显示 - 在每次按下条形按钮时 - 正在调用的“sectionIndex”方法以及 UITableView 中显示的相应标签。

这太疯狂了 - 如果我有 2 个“活动”作业和 2 个“非活动”作业,并且我正在使用条形按钮在相应的查询之间来回切换......那么无论哪个部分标签与初始查询相关联显示为所有后续表格视图做好准备。

似乎 sectionNameKeyPath 字段仅在结果集中有不同 # 个结果时由 FetchedResultsController 调用?实际结果不同 - 作业名称在实际行中正确显示 - 但同样,我不认为部分标签有错误或正确询问 NSFetchedResultsController 部分标签。我正在使用以下内容:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section 
    int count = [[results_ sections] count];
    if (count > section) 
        id <NSFetchedResultsSectionInfo> sectionInfo = [[results_ sections] objectAtIndex:section];
        return [sectionInfo name];
    
    return nil;

其中 results_ 是我为每个查询重新构建的 NSFetchedResultsController。

我错过了什么吗?有没有办法手动清除 Core Data 缓存,让它不再那么聪明,并且在每次查询时,肯定会查找 sectionNameKeyPath?

为了它的价值,我取消了 xcdatamodel 中字段的“瞬态”选项,但我得到了相同的结果。

最后一个异常情况是,当我将第一个作业创建为非活动(不是默认的启动视图)时 - 如果我还创建了一个活动作业......非活动部分标签会粘在两者上。此外,当我关闭应用程序并重新开始时......非活动部分标签仍然显示 --- 即使在标题屏幕上,我正在显示应该显示完全不同标签的活动作业。

我不能不认为这是一个核心数据问题。重新启动应用程序返回的数据如此不正常是没有意义的。

【问题讨论】:

顺便说一下,这段代码(同时执行)显示了行的正确值: Job job = (Job)[results_ objectAtIndexPath:indexPath]; cell.textLabel.text = 工作名称;即:我知道查询正在运行,并且新结果在“results_”对象中可用。 (*** 的注释编辑器从包含的代码 sn-p 中删除了所需的星号)。 请出示您的 NSFetchedResultsController 初始化代码。有一个缓存选项,我怀疑您设置了缓存。 确实有效。我正在使用: results_ = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context_ sectionNameKeyPath:@"sectionIndex" cacheName:@"JobsControllerCache"];而如果我将缓存设置为 nil - 它可以工作。谢谢。 将此评论添加到答案中,我会将其标记为已解决(您将获得积分)。 【参考方案1】:

根据Marcus S. Zarra's 的评论,我将 cacheName 设置为 nil:

results_ = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
            managedObjectContext:context_ 
            sectionNameKeyPath:@"sectionIndex" 
            cacheName:nil];

【讨论】:

以上是关于为啥 NSFetchedResultsController 不能正确加载章节标题?的主要内容,如果未能解决你的问题,请参考以下文章

核心数据保存竞争条件错误

在 Swift 3 中难以配置 NSFetchedResultsController

如何根据计算的属性过滤来自 NSFetchedResultsController 的结果?

你应该同步运行方法吗?为啥或者为啥不?

为啥使用 glTranslatef?为啥不直接更改渲染坐标?

为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?