NSFetchedResultsController和NSOrderedSet关系

时间:2012-01-06 13:21:11

标签: iphone objective-c ios core-data ios5

我遇到了一个问题(老实说,理解问题),NSFetchedResultsController和iOS 5中提供的新NSOrderedSet关系。

我有以下数据模型(好吧,我的真实不是抽屉和袜子!)但这只是一个简单的例子:

enter image description here

Drawer和Sock都是Core Data模型/商店中的NSManagedObjects。在Drawer socks关系是与<{1}}的有序到多个关系。想法是袜子按特定顺序放在抽屉里。在Sock Sock关系是drawer关系的倒数。

在UIViewController中,我正在基于这些实体绘制UITableView。我使用socks来喂餐桌。

NSFetchedResultsController

当我运行时,我得到以下错误:- (NSFetchedResultsController *)fetchedResultsController1 { if (_fetchedResultsController1 != nil) { return _fetchedResultsController1; } NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Sock" inManagedObjectContext:[NSManagedObjectContext MR_defaultContext]]; [fetchRequest setEntity:entity]; NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"drawer.socks" ascending:YES]; [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]]; self.fetchedResultsController1 = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[NSManagedObjectContext MR_defaultContext] sectionNameKeyPath:nil cacheName:@"SocksCache"]; self.fetchedResultsController1.delegate = self; return _fetchedResultsController1; }

这对我来说很有意义,因为关系是*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'to-many key not allowed here'而不是单个实体可以进行比较以进行排序。

我想要实现的是NSOrderedSet按照Socks关系中指定的顺序显示在UITableView中。我真的不想要排序顺序但是socks,这是一个很好的组件,坚持必须有一个。如何告诉它在Drawer实体上使用socks命令。我不希望表格显示抽屉实体。

注意:我仅在iOS5应用程序中使用此功能,因此可以使用有序关系。

任何可以向我提供任何指示的人都将不胜感激。谢谢你的时间。

编辑:所以显示袜子的tableview只对一个抽屉这样做。我只想让表视图遵守socks关系包含的顺序。我不确定如何设置排序标准以确保发生这种情况。

6 个答案:

答案 0 :(得分:5)

达明,

您应该让NSFetchRequest使用有序集的数组形式。它会运作良好。您的控制器需要一个属性来排序。因此,您还需要指定它。

安德鲁

答案 1 :(得分:3)

您可以为Sock提供索引属性并按顺序对袜子进行排序:

sock01.index = [sock01.drawer.socks indexOfObject:sock01];

答案 2 :(得分:3)

我在寻找OP提出的确切问题的答案时找到了这个帖子。

我从未在tableView中找到任何在不添加其他排序字段的情况下显示此类数据的示例。当然,添加排序字段几乎消除了使用有序关系的任何好处。所以考虑到我有这个工作,我认为如果我在这里发布我的代码可能对其他人有相同的帮助。事实证明它非常简单(比使用额外的排序字段简单得多)并且具有明显的良好性能。一些人可能没有意识到(最初包括我)是“有序,多对多”关系属性的类型(NSOrderedSet)有一个获取objectAtIndex的方法,而{ {1}}具有插入和移除NSMUtableOrderedSet的方法。

我避免使用objectAtIndex,正如一些海报所暗示的那样。我没有使用数组,没有用于排序的附加属性,也没有使用谓词。我的代码处理NSFetchedResultsController,其中有一个行程实体和许多地方实体,其中tableView是“有序,多对”关系字段。我已启用编辑/重新排序,但没有删除单元格。方法itinerary.places显示了我如何使用重新排序更新数据库,尽管为了良好的封装,我应该将数据库重新排序移动到我的类别文件中的地方管理对象。这是整个moveRowAtIndexPath

TableViewController.m

答案 3 :(得分:2)

据我了解此功能,它允许在每个Sock中订购Drawer个。正如Apple在documentation写道:

  

只有在关系具有内在排序时才应使用它们   对于自己的表示至关重要 - 例如食谱中的步骤。

这意味着您无法使用已排序关系获取所有Sock。排序Sock只能在每个Drawer对象中使用。

答案 4 :(得分:1)

正如我刚刚回答here,我更喜欢通过类别向NSManagedObject添加新属性。

只需添加方法:

- (NSUInteger)indexInDrawerSocks
{
    NSUInteger index = [self.drawer.socks indexOfObject:self];
    return index;
}

然后在NSFetchedResultsController中,使用sort descriptor:

fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"indexInDrawerSocks" ascending:YES]];

答案 5 :(得分:1)

为adonoho(感谢队友)的答案添加更多的清晰度,这有助于我解决问题 - 而不是试图将任意排序关键字指定为任何排序键,我也无法使用,指定谓词中的属于 - 关系,用于在获取的结果控制器中选择所需的实体,并将所属关系指定为排序键。

这满足了将结果放在具有所有优点的NSFetchedResultsController中的主要目的,并且尊重多对多关系中的顺序。

在这个特定的例子中(抽屉取袜子):

// socks belong-to a single drawer, sort by drawer specified sock order
fetchRequest.sortDescriptors = @[[[NSSortDescriptor alloc] initWithKey:@"drawer" ascending:YES]];

// drawer has-many socks, select the socks in the given drawer
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"drawer = %@", drawer];

基本上,它使用给定的抽屉来指定哪些袜子应该进入NSFetchedResultsController,以及由多对多关系指定的排序。

通过核心数据SQL调试查看生成的SQL(使用不同实体名称从我的示例中注释):

CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, ...fields..., t0.ZDRAWER, t0.Z_FOK_DRAWER FROM ZSOCKS t0 WHERE  t0.ZDRAWER = ?  ORDER BY  t0.Z_FOK_DRAWER

您可以使用Z_FOK_DRAWER列查看SQL排序,Core Data将该列用于该袜子的位置。