我遇到了一个问题(老实说,理解问题),NSFetchedResultsController和iOS 5中提供的新NSOrderedSet关系。
我有以下数据模型(好吧,我的真实不是抽屉和袜子!)但这只是一个简单的例子:
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关系包含的顺序。我不确定如何设置排序标准以确保发生这种情况。
答案 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将该列用于该袜子的位置。