如何形成谓词以从核心数据中获取包含数组中字符串元素的对象

how to form predicate to get objects from Core Data that contain string elements from Array

我需要创建一个谓词来从核心数据中获取对象, 我的实体 "Form" 看起来像这样:

@interface EEForm (CoreDataProperties)
@property (nullable, nonatomic, retain) NSDate *date;
@property (nullable, nonatomic, retain) NSString *descriptor;
@property (nullable, nonatomic, retain) NSString *location;
@property (nullable, nonatomic, retain) NSMutableSet<Participants *> *participants;

实体 "Participants" 看起来像这样:

@interface Participants (CoreDataProperties)

@property (nonatomic, assign) NSInteger indexRow;
@property (nullable, nonatomic, retain) NSString *participant;
@property (nullable, nonatomic, retain) EEForm *form;

我想在参与者字段的基础上获取对象,它包含给定数组中的所有对象(这个数组由字符串对象组成,它会根据用户的选择而变化)。 获取请求由 FetchResultController 执行。我在它的初始化中设置了谓词。

我是那样做的,但它包括所有至少包含给定数组中一个对象的对象。

- (NSFetchedResultsController *)fetchResultController {
    if(_fetchResultController != nil) {
        return _fetchResultController;
    }

    NSPredicate *lPredicate = [NSPredicate predicateWithFormat:@"ANY participants.participant IN %@", _selectedForPredicatel];
    NSFetchRequest *lRequest = [[NSFetchRequest alloc]init];
    [lRequest setPredicate:lPredicate];
    NSEntityDescription *lEntity = [NSEntityDescription entityForName:@"Form" inManagedObjectContext:self.managedObjectContext];
    [lRequest setEntity:lEntity];
    [lRequest setFetchBatchSize:10];
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey:@"date" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sortDescriptor, nil];
    [lRequest setSortDescriptors:sortDescriptors];
    NSFetchedResultsController *fetchResultController = [[NSFetchedResultsController alloc]initWithFetchRequest:lRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
    fetchResultController.delegate = self;
    self.fetchResultController = fetchResultController;
    NSError *error = nil;
    if(![[self fetchResultController] performFetch:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
    return fetchResultController;
}

能否请您建议如何正确设置谓词以过滤包含给定数组中所有元素的对象。

编辑: 用于谓词的数组如下所示:

   _selectedForPredicatel = [[NSMutableArray alloc]initWithObjects:@"Child",@"Adult", @"Group of people", @"Family", @"Teenager", nil];

每次用户选择过滤 'Form' 对象的参数时,这个数组都会更新,所以我需要根据它来完成获取请求。因此,如果 'Form' 包含了参与者:@"Child"、@"Adult",但是在数组 _selectedForPredicate 中有对象:@"Adult"、@"Group of people",在这个如果这个 'Form' 不应该被获取。应仅获取包含 _selectedForPredicate 数组的两个元素的 'Form'。 非常感谢任何建议。

您可以使用 ALL 代替 ANY :

 NSPredicate *lPredicate = [NSPredicate predicateWithFormat:@"ALL participants.participant IN %@", _sortByParticipants];

这将检查是否所有 objects 都在您的 collection 中。

如果对于每个用户的选择,至少有一个 Participant 具有匹配的 participant 属性,则您希望包含这些表单。

如果参与者姓名是唯一的(至少每个 Form),您可以计算匹配项并与用户选择的计数进行比较。但如果没有,则需要创建一个谓词分别测试用户的每个选择,然后将结果组合成一个大谓词:

NSPredicate *template = [NSPredicate predicateWithFormat:@"(SUBQUERY(participants, $p, $p.participant == $SELECTED).@count > 0)"];
NSMutableArray *predicateArray = [NSMutableArray array];
for (NSString *testString in _selectedForPredicatel) {
    NSDictionary *subsVars = @{@"SELECTED" : testString};
    NSPredicate *testPredicate = [template predicateWithSubstitutionVariables:subsVars];
    [predicateArray addObject:testPredicate];
}
NSPredicate *finalPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicateArray];
NSLog(@"finalPredicate is %@", finalPredicate);
NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:@"ListEntity"];
fetch.predicate = finalPredicate;

此处 template 是一个虚拟谓词,使用 $SELECTED 作为用户选择的占位符。 for 循环使用它为每个用户的选择创建一个谓词并将其添加到一个可变数组中。最终谓词是通过使用 AND 子句组合谓词数组构建的。

它非常混乱(最终谓词已经够糟糕了,底层的 SQL 太可怕了)所以性能可能会很差。