核心数据:如何检查多对多关系的存在

时间:2009-09-10 17:14:49

标签: iphone core-data

我有一个“歌曲”实体和一个“标签”实体,它们之间有很多关系。歌曲可以有多个标签,标签可以应用于多首歌曲。

我想检查歌曲是否有与之关联的特定标签。如果歌曲中有与之关联的标签,我想在表格视图中显示一个复选标记。

对于类似的逻辑,在Apple“TaggedLocations”示例代码中,进行以下检查以检查是否存在关系。

if ([event.tags containsObject:tag]) {
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
}   

如果数据库中有很多标签,这可能效率很低,因为这会在内存中获取所有标签。如果我在这里错了,请纠正我。

是否有更有效的方法来检查歌曲是否与特定标签相关联,而不是检入Song.Tags?

2 个答案:

答案 0 :(得分:5)

如果完全没有记录,这实际上很容易。您希望使用具有set操作的谓词创建获取请求。如果我们想象您的Tag模型有一个名为tagValue的属性,那么您关心的谓词是“ANY tags.tagValue =='footag'”

NSString *tagSearch = @"footag";

// However you get your NSManagedObjectContext.  If you use template code, it's from
// the UIApplicationDelegate
NSManagedObjectContext *context = [delegate managedObjectContext];

// Is there no shortcut for this?  Maybe not, seems to be per context...
NSEntityDescription *songEntity = [NSEntityDescription entityForName:@"Song" inManagedObjectContext:context];

NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:songEntity];

// The request looks for this a group with the supplied name
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagValue == %@", tagSearch];
[request setPredicate:predicate];

NSError *error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];

[request release];

答案 1 :(得分:3)

你是对的,使用该代码将检索整个集合,对象比较可能非常复杂,具体取决于对象实体的一部分属性和关系。

无论如何,你无法避免包含的集合比较。也许,您可以做的最好的事情是通过要求Core Data仅检索NSManagedObjectID对象来避免获取所有属性/关系。

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Tag" inManagedObjectContext:[self managedObjectContext]]]; 
[fetchRequest setResultType:NSManagedObjectIDResultType];

NSManagedObjectID对象保证是唯一的,因此您可以安全地使用它们来检查集合包含。从性能角度来看,这应该更有效率。