3

我有一个简单的目录管理器功能,其中包含类别中的项目,除了一个项目可以在多个类别中。

项目具有“父母”键,即父类别的 NSSet

类别有“项目”键,它是其子项目的 NSOrderedSet

我正在使用NSFetchedResultController它的代表来用物品填满我的桌子

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Item" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];

fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(ANY parents == %@)", self.category];

[fetchRequest setFetchBatchSize:30];
[fetchRequest setSortDescriptors:@[????????];

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;

NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}

所以使用这段代码我可以得到 self.category 中的项目列表

在我的 UI 中,我有Drag and Drop功能。所以我可以在类别内移动项目。

我的问题: Category1 和 Category2 都包含对相同项目 Item1 和 Item2 的引用。我需要在 Category1 中有 Item1、Item2 的订单,在 Category2 中有 Item2、Item1 的订单。这就是为什么我将 category.items 属性设置为NSOrderedSet.

但我只是不能按它们在 category.items 中的索引对项目进行排序

我尝试在排序描述符中使用块 - 没用,我尝试在排序描述符中使用选择器 - 没用,我尝试对排序描述符进行子类化 - 以某种方式工作,但在我更改它们的索引时不更新项目类别.项目。
在我的 NSSortDescriptorSubclass 中像这样:

- (NSComparisonResult)compareObject:(Item*)object1 toObject:(Item*)object2 {

int index1 = [self.category.items indexOfObject:object1];
int index2 = [self.category.items indexOfObject:object2];

if (index1 > index2) {
    return NSOrderedDescending;
} else if (index1 < index2) {
    return NSOrderedAscending;
}

return NSOrderedSame;

} 但是如果我在 Category.items 中更改订单,项目订单将不会在我的 UI 中更新

所以请帮我按照 category.items 集中的索引对项目进行排序。也许有一种方法可以通过一些键、运算符、表达式或其他任何东西来做到这一点。谢谢。

4

2 回答 2

2

我建议您不要使用有序对多关系。似乎它们并没有真正按预期工作,也不符合您的需求。

相反,您需要引入自己的属性来进行排序。你可以有一个实体,它与 和以及一个属性categoryItem都具有一对一关系。CategoryItemsequence

在您的 FRC 中,您获取categoryItem实体并在显示时仅用于categoryItem.item访问项目的属性。当您重新排序(例如通过拖放)时,您必须重新编号所有categoryItems 并分配正确的序列号。

- 编辑 -

要在项目的某些细节发生更改时将其标记categoryItem为“脏”:您可以实现如下所示的markDirty方法categoryItem

// CategoryItem.m
-(void)markDirty {
    [self willChangeValueForKey:@"sequence"];
    [self didChangeValueForKey:@"sequence"];
}

// EditItemController.m
item.attribute = newAttribute; 
for (CategoryItem *i in item.categoryItems) { [i markDirty]; }
于 2013-04-02T16:51:01.310 回答
1

Core Data 中的一对多关系是NSSets,而不是NSOrderedSets。由于这个原因,类别中的项目的索引不会被保存。您可以将另一个实体添加到您的核心数据模型中,称为IndexValue. IndexValue将有两个属性,categoryId或者categoryName(无论哪个有意义)然后categoryIndex. Item然后将与该实体具有一对多的关系(以及一对一的反向关系,因为不需要重用这些实体,它们应该是唯一的)。对于其中的每Category一个,Item都会IndexValue创建一个。

编辑:似乎添加了一个有序属性以支持OS X 10.7 和 iOS 5NSOrderedSet中的一对多关系。这必须是您的目标和使用。关于这个特性的文档很少,但是在获取关系时应该保持顺序而不需要使用s。至于更改顺序,我不确定这是如何支持的。与我概述的上述方法相比,使用此方法对大量数据的性能较低。NSSortDescriptor

于 2013-04-02T16:15:13.943 回答