如何形成谓词以从Core Data获取包含Array中的字符串元素的对象 [英] how to form predicate to get objects from Core Data that contain string elements from Array

查看:74
本文介绍了如何形成谓词以从Core Data获取包含Array中的字符串元素的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要创建一个谓词以从核心数据中获取对象,
我的实体表单如下所示:

I need to create a predicate to get object from core data, My entity "Form" looks like that:

@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执行。我将谓词设置为初始化。

I want to get objects on the base of participants field, that contains all objects from a given array (this array consist of string objects and it changes dependently of what the user selects). Fetch request is performed by FetchResultController. I set the predicate in initialisation of it.

我是用这种方式完成的,但是它包括所有包含至少一个给定数组中对象的对象。

I did it in that way, but it includes all objects that contains at least one object from the given array.

- (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;
}

请问如何正确设置谓词以过滤包含所有元素的对象

Could you please advice how to set predicate properly to filter objects that contain all elements from the given array.

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

array that is used for predicate looks like that:

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

每次用户选择用于过滤 Form对象的参数时,此数组都会更新,所以我需要提取要根据它完成的请求。因此,如果表单包含参与者:@儿童,@成人,但在_selectedForPredicatel数组中有对象:@成人,@一群人,在这种情况下,此表单不应被拿来。仅应提取包含_selectedForPredicatel数组的两个元素的表单。
非常感谢您提供任何建议。

every time user selects parameters by which filter 'Form' objects, this array is updating, so I need fetch request to be done according to it. So if 'Form' has included participants: @"Child",@"Adult", but in an array _selectedForPredicatel there are objects: @"Adult", @"Group of people", in this case this 'Form' shouldn't be fetched. Should be fetched only that 'Form'that includes both elements of _selectedForPredicatel array. Thanks a lot for any advice.

推荐答案

对于每个用户的选择,如果要包含表单, ,至少有一个参与者具有匹配的参与者属性。

You want to include the forms if, for each of the user's selections, there is at least one Participant that has a participant attribute that matches.

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

If the participant names were unique (at least for each Form), you could count the matches and compare to the count of the user's selections. But if not, you need to create a predicate test each of the user's selections separately, and then combine the results into one big predicate:

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 子句复合谓词数组而构建的。

Here template is a dummy predicate using $SELECTED as a placeholder for the user's selection. The for loop uses this to create a predicate for each of the user's selections and adds it to a mutable array. The final predicate is built by compounding the array of predicates using AND clauses.

这很混乱(最终谓词够糟糕,底层的SQL太可怕了),因此性能可能会很糟糕。

It's pretty messy (the final predicate is bad enough, the underlying SQL is horrible) so performance might be dismal.

这篇关于如何形成谓词以从Core Data获取包含Array中的字符串元素的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆