如何使用具有NSFetchedResultsController的CoreData有序关系

4
我有一个Items Entity和一个Tags Entity。
Items可以有多个Tags,而Tags也可以链接到多个Items(多对多关系)。
这种关系是“有序关系”(使用IOS5中的有序关系),并且是双向的。
我想使用NSFetchedResultsController获取所有Tag下的Items。
查询:
1.是否可以在NSFetchRequest和NSFetchedResultsController中使用有序关系?
2.如何指定“Sort Descriptor”?
3.我尝试了两个谓词。第一个没有结果,第二个却有结果。为什么第一个不起作用?同时,如何指定排序描述符以使用CoreData自动管理此关系的排序顺序?
没有起作用的:[NSPredicate predicateWithFormat:@"ANY tags == %@", yyy];
起作用的:但效率较低:[NSPredicate predicateWithFormat=@"ANY tags.tagID ==%@", xxx];
1个回答

2

1 - 是的,这是可能的。当您创建映射文件时,请确保将关系类型从NSSet更改为NSArray,如下所示:

    @class Tags

    @interface Entity : NSManagedObject
    ...
    @property (nonatomic, retain) NSOrderedSet *tags;
    ...
    @end

    @interface Entity (CoreDataGeneratedAccessors)
    ...
    - (void)addEntityTags:(NSOrderedSet *)values;
    - (void)removeEntityTags:(NSOrderedSet *)values;
    ...
    @end

转换为:

    @class Tags

    @interface Entity : NSManagedObject
    ...
    @property (nonatomic, retain) NSArray *tags;
    ...
    @end

    @interface Entity (CoreDataGeneratedAccessors)
    ...
    - (void)addEntityTags:(NSArray *)values;
    - (void)removeEntityTags:(NSArray *)values;
    ...
    @end

2 - 在创建获取请求时,您可以指定排序描述符,如下所示:

    NSFetchRequest *fetchRequest [NSFetchRequest new];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Entity" inManagedObjectContext:myManagedObjectContext];

    [fetchRequest.setEntity: entity];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"tags" ascending:<YES|NO>]];
    [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"ANY tags == %@", yyy]];

    NSFetchResultsController *myFetchResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:myManagedObjectContext setcionNameKeyPath:nil cacheName:nil];
    myFetchResultsController.delegate = self;

    [fetchRequest release]; // Forget that if using ARC.

    NSError *error = nil;

    if (![myFetchResultsController performFetch:&error]) {
        NSLog(@"Failed to fetch data: %@", error);
    }

3 - 如果您使用该属性,就不需要为标记指定谓词。如果您想进一步对标记进行排序,可以在该数组上使用排序描述符,如下所示:

    NSSortDescriptor *tagDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"<tags field to sort on>" ascending:<YES|NO>];
    NSArray *sortedTags = [tagsProperty sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptors]];

你可以简单地从该属性中读取标记信息。
希望有所帮助!

等一下。你在第三步做的那个谓词,是不是意味着你正在尝试获取所有具有特定标签的项目?因为你最初的问题是关于获取项目的所有标签。 - Simon Germain
好的,这将会极大地改变我的答案。有一个有趣的事实:从苹果的文档中可以看出,NSOrderedSet 似乎没有扩展 NSSet,后者有一个名为“filterSetUsingPredicate”的方法。在 NSOrderedSet 中并没有这样的东西。也许有序集合并不是你在这里需要的。 - Simon Germain
尝试在映射文件中将该属性更改为使用NSArray而不是NSOrderedSet,并查看谓词是否能够正常工作。NSArray将保留当前顺序。 - Simon Germain
没有起作用。第一个查询仍然不起作用。第二个可以。 - siasl
我提出了一个新的相关问题。最终我自己编写了有序关系实现。但是还有一个小问题。如果您能够看一下https://dev59.com/iGjWa4cB1Zd3GeqPpli5,我将不胜感激。 - siasl
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接