核心数据:NSPredicate,可查看两个实体

Vla*_*dan 1 core-data objective-c nsfetchrequest ios

问题是我不知道如何NSPredicate在两个实体中查看.有任何想法吗?

我们假设我有2个实体:

Library:
1 lib_id
2 name
3 address
Run Code Online (Sandbox Code Playgroud)

和:

Books
1 book_id
2 book_name
3 book_author
4 lib_id
Run Code Online (Sandbox Code Playgroud)

它们之间没有任何核心数据关系.我想创建一个获取请求,该请求将返回包含至少一本书的所有库的NSArray.

我认为它是这样的:

NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescriptor *entity = [NSEntityDescriptor entityForName:@"Books" inManagedObjectContext:context];
 // some NSPredicate...
array = [context executeFetch ...];
Run Code Online (Sandbox Code Playgroud)

Tom*_*ton 8

它比你想象的要复杂得多,但并非不可能.

您的数据模型lib_id在两个实体上的使用以及您无法在实体之间添加核心数据关系的注释表明您陷入了经典陷阱:您将Core Data视为关系数据库.Core Data的API不像关系数据库那样设计.你可以让它以这种方式工作,但是你应该意识到你正在竭尽全力使核心数据变得更加困难.如果下面的解决方案看起来很复杂,那是因为你做的核心数据错了.

如果您正在使用Core Data,因为它打算使用 - 在这种情况下,两个实体之间存在关系 - 查找将很简单.您可以为每个Library在其books关系中没有条目的人进行提取.

话虽如此,您可以分两步解决当前问题.

首先,获取lib_id在实例上使用的每个唯一值Books.以下内容将为您提供NSArray与唯一值匹配的字符串:

NSFetchRequest *bookRequest = [NSFetchRequest fetchRequestWithEntityName:@"Books"];
[bookRequest setPropertiesToFetch:@[@"lib_id"]];
[bookRequest setResultType:NSDictionaryResultType];
[bookRequest setReturnsDistinctResults:YES];

NSError *error = nil;
NSArray *libIdsInBooksDicts = [[self managedObjectContext] executeFetchRequest:bookRequest error:&error];
if (libIdsInBooksDicts == nil) {
    NSLog(@"Fetch error: %@", error);
    return;
}

NSArray *libIdsInBooks = [libIdsInBooksDicts valueForKey:@"lib_id"];
Run Code Online (Sandbox Code Playgroud)

上面的最后一行是因为libIdsInBooksDicts实际上包含一个字典数组,而每个字典又有一个名为key的键lib_id和一个实际ID的值.你只想要这些价值观.

接下来,查找每一个Librarylib_id是你刚列表:

NSFetchRequest *libRequest = [NSFetchRequest fetchRequestWithEntityName:@"Library"];
[libRequest setPredicate:[NSPredicate predicateWithFormat:@"lib_id in %@", libIdsInBooks]];

error = nil;
NSArray *librariesWithAtLeastOneBook = [[self managedObjectContext] executeFetchRequest:libRequest error:&error];
if (librariesWithAtLeastOneBook == nil) {
    NSLog(@"Fetch error: %@", error);
    return;
}
Run Code Online (Sandbox Code Playgroud)