使用NSFetchedResultsController动态创建节

时间:2013-01-05 11:50:13

标签: ios objective-c

我正在使用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?如果你们可以帮助指导我,我会非常感激。如果您需要我发布更多代码,我会很高兴。

的问候,
麦克

1 个答案:

答案 0 :(得分:26)

如果您希望FRC包含部分,则必须向获取请求添加排序描述符,并且该排序描述符不能基于瞬态属性。

请参阅initWithFetchRequest:managedObjectContext:sectionNameKeyPath:cacheName:`:

的文档
  

如果控制器生成节,则第一个排序描述符   该数组用于将对象分组为多个部分;它的关键必须   要么与sectionNameKeyPath相同,要么与相对顺序相同   使用其键必须与使用sectionNameKeyPath匹配。

“核心数据编程指南”中的

Fetch Predicates and Sort Descriptors

  

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

这意味着无法创建纯粹基于瞬态属性的部分。您需要一个持久属性来创建节的排序。

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

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

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

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