【问题标题】:Creating sections with NSFetchedResultsController, on the fly使用 NSFetchedResultsController 动态创建部分
【发布时间】:2013-01-05 11:50:12
【问题描述】:

我使用NSFetchedResultsController (NSFRC) 在UITableView 中显示信息。我正在尝试为用户创建选项以按部分而不是按字母顺序对单元格进行排序。问题是,然后将使用下载的信息来确定这些部分。最重要的是,每个项目的部分将相对经常更改,因此我不想保存该部分。在我对类似问题的研究中,我注意到提到了瞬态属性,但在我不确定是否可以使用它们之前,我从未使用过这些属性,因为所有的计算都是在数据已经加载后完成的,并且我还希望这个解决方案与我之前的Core Data database 兼容。另外我在Core Data 方面也不是特别出色,(也不是Objective-C!)所以我不完全确定我将如何去做。

所以如果我们使用瞬态属性,这就是我想要的(下一点是理论上的,因为我不知道瞬态属性是否是正确的前进方式)。我想要 4 个可能的部分,0-3(我将使用 TableView delegate 重命名它们以解决排序问题)。计算完成后,将为每个单元格分配瞬态属性(如果需要,默认部分将为 2)。我希望这一切都有意义。

好的,现在是一些理论代码。首先,我在数据模型屏幕中创建瞬态属性,并通过选中瞬态复选框使其瞬态......听起来很简单。

willDisplayCell 的计算代码中(出于几个原因需要在 wDC 中完成),实体可以这样保存:

MyEntity *myEntity = [self.fetchedResultsController objectAtIndexPath:indexPath];

myEntity.sectionTransientProperty = 2;

if (![self.managedObjectContext save:&error]) {
    NSLog(@"Error: %@", error);
    FATAL_CORE_DATA_ERROR(error);
    return;
}  

完成了,对吧?这就是我们为瞬态属性赋值的方式吗?

然后我在分配时更改 NSFRC 中的排序选项:

fetchedResultsController = [[NSFetchedResultsController alloc]
                                initWithFetchRequest:fetchRequest
                                managedObjectContext:self.managedObjectContext
                                sectionNameKeyPath:@"sectionTransientProperty"
                                cacheName:@"MyEntity"];

我们做得怎么样,我还需要做什么?还是我把这个弄错了,我应该放弃Core Data and NSFRC? 如果你们能帮助指导我完成这个,我真的很感激。如果您需要我发布更多代码,我很乐意。

问候,
迈克

【问题讨论】:

    标签: ios objective-c


    【解决方案1】:

    如果你想要一个带有部分的 FRC,你必须在 fetch 请求中添加一个排序描述符,并且该排序描述符不能基于瞬态属性。

    查看initWithFetchRequest:managedObjectContext:sectionNameKeyPath:cacheName:`:的文档

    如果控制器生成节,则第一个排序描述符在 该数组用于将对象分组为部分;它的钥匙必须 与 sectionNameKeyPath 或相对排序相同 使用其密钥必须与使用 sectionNameKeyPath 匹配。

    和《核心数据编程指南》中的Fetch Predicates and Sort Descriptors

    另一方面,SQL 存储编译谓词并排序 描述 SQL 并评估数据库本身的结果。 这主要是为了性能,但这意味着评估 发生在非 Cocoa 环境中,因此排序描述符(或 依赖于 Cocoa 的谓词)不能工作。支持的排序 选择器是...
    此外,您不能使用 SQLite 存储对瞬态属性进行排序。

    这意味着您不能纯粹根据瞬态属性创建部分。您需要一个持久属性来为这些部分创建排序。

    更新:sectionNameKeyPath 这样的瞬态属性的典型用法是:您的对象具有“timeStamp”属性,并且您希望将对象分组为每个月一个部分的部分(请参阅DateSectionTitles 来自 iOS 开发人员库的示例代码)。在这种情况下,您有

    • 一个持久属性“timeStamp”,
    • 使用“timeStamp”作为获取请求的第一个排序描述符,
    • 临时属性“sectionIdentifier”用作sectionNameKeyPath。 “sectionIdentifier”是从“timeStamp”计算出来的,并返回一个字符串,表示时间戳的年份和月份,例如“2013-01”。

    FRC 做的第一件事是根据“timeStamp”属性排序所有获取的对象。然后根据“sectionIdentifier”属性将对象分组

    因此,对于 FRC 将对象分组到您真正需要一个持久属性的部分。最简单的解决方案是将持久属性“sectionNumber”添加到您的实体,并将其用于“sectionNameKeyPath”作为第一个排序描述符。

    【讨论】:

    • 我已经在使用实体的名称按字母顺序排序,但是我听说使用 sectionNameKeyPath:@"sectionTransientProperty" 可以让您从瞬态设置部分。
    • @Mackey18:第一个排序描述符必须使用与 sectionNameKeyPath 相同的键,或者使用其键的相对排序必须与使用 sectionNameKeyPath 匹配。 - 这个条件是否满足?
    • 嗯,他们是怎么在这里做到的:stackoverflow.com/questions/1384345/…?好的,如果瞬态属性不行,我怎样才能实现我的期望?
    • @Mackey18:我已经更新了答案,提供了更多关于持久性和瞬态属性如何与 FRC 部分一起使用的信息。我认为stackoverflow.com/questions/1384345/… 也是如此:他们使用从某个持久属性计算的瞬态属性。
    • @Mackey18:根据“Core Data Model Versioning and Data Migration Programming Guide”中的Lightweight Migration,Core Data 可以通过自动数据迁移(又名轻量级迁移)执行添加新属性.
    猜你喜欢
    • 2010-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多