如何形成谓词以从Core Data中获取包含Array中的字符串元素的对象

时间:2016-05-26 15:17:08

标签: ios core-data nspredicate

我需要创建一个谓词来从核心数据中获取对象, 我的实体“表格”看起来像那样:

@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;

实体“参与者”看起来像这样:

@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”,但是在数组_selectedForPredicatel中有对象:@“Adult”,@“Group of people”,在这种情况下,这个'Form'不应该被抓住了。应该只获取'Form'包含_selectedForPredicatel数组的两个元素。 非常感谢任何建议。

2 个答案:

答案 0 :(得分:1)

而不是任何你可以使用ALL:

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

这将检查所有对象是否都在您的收藏中。

答案 1 :(得分:1)

如果对于每个用户的选择,至少有一个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很糟糕)所以性能可能很糟糕。