在NSPredicate中结合“AND”和“OR”条件

再次需要更多的帮助,构build我的NSPredicates 🙁

Category { name:string subs<-->>SubCategory } SubCategory { name:string numbervalue:NSNumber } 

我想知道如何用ANDOR创build一个谓词。

例如,我想返回每个类别的名称==“category_name”,也有一个数值为“valueA” “valueB”的子类别。

我已经尝试了所有可能的谓词构造方法的组合,但是我只是无法让它工作。

这是迄今为止我最好的尝试。

 NSPredicate *predicate=[NSPredicate predicateWithFormat@"(name== %@) AND (ANY subs.numbervalue==%@ OR ANY subs.numbervalue==%@)", @"aname", value1, value2]; 

编辑1

第二次尝试。 对“numbervalue”的过滤仍然不起作用。

 NSNumber valueA=[NSNumber numberWithInt:20]; NSNumber valueA=[NSNumber numberWithInt:90]; NSArray *arr=[NSArray arrayWithObject:valueA,valueB,nil]; predicate=[NSPredicate predicateWithFormat:@"(name==%@)AND(ANY subs.numbervalue IN %@)",@"aname",arr]; 

编辑2

我已经尝试通过numberValue进行过滤,并将名称全部留下。

1)使用这个结果会导致整个集合被返回,即使集合中只有一个项目具有该值。

 predicate=[NSPredicate predicateWithFormat:@"(ANY subs.numbervalue IN %@)",arr]; 

2)使用这个结果会导致同样的问题,即使只有一个匹配,这个集合中的每个项目都会被返回。

 predicate=[NSPredicate predicateWithFormat:@"((SUBQUERY(subs, $x, $x.numbervalue == %@ or $x.numbervalue == %@).@count > 0)", value1, value2]; 

也使用最简单的版本导致同样的问题….我没有注意到这一点。

 NSPredicate *predicate=[NSPredicate predicateWithFormat@"(ANY subs.numbervalue==%@ ,valueA]; 

所以我觉得我的问题已经缩小了。

类别是一个实体。 子类别是一个实体。

类别与子类别具有一对多的关系,并被表示为子类别的NSSet。

每个子类别都有一个名为numbervalue的属性。

编辑3

为了testing我有2个分类。 两个类别都有10个子系列,每个系列的数字值都是1-10。

使用这个代码,两个类别都会返回,每个类别都有10个subs。

预期的结果是两个类别返回,每个只有2个子。

我已经找出所有的对象,数据是正确的。 问题是我不能返回已过滤子类别的类别。

 NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSManagedObjectContext *context=[[DataSource sharedDataSource]managedObjectContext]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Category" inManagedObjectContext:context]; [fetchRequest setEntity:entity]; [fetchRequest setFetchBatchSize:20]; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]; NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil]; NSPredicate *predicate; NSNumber *a=[NSNumber numberWithFloat:1]; NSNumber *b=[NSNumber numberWithFloat:2]; predicate=[NSPredicate predicateWithFormat:@"(SUBQUERY(subs,$x,$x.numbervalue==%@ or $x.numbervalue==%@).@count> 0)",a,b]; [fetchRequest setPredicate:predicate]; [fetchRequest setSortDescriptors:sortDescriptors]; NSError *error = nil; [NSFetchedResultsContoller deleteCacheWithName:nil]; NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:@"name" cacheName:@"Master"]; aFetchedResultsController.delegate = self; self.fetchedResultsController = aFetchedResultsController; if (![self.fetchedResultsController performFetch:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } 

我将使用SUBQUERY来执行以下操作。

 [NSPredicate predicateWithFormat@"(name == %@) AND (SUBQUERY(subs, $x, $x.numbervalue == %@ or $x.numbervalue == %@).@count > 0)", @"aname", value1, value2]; 

试试吧,让我知道。

另一个解决scheme可能是抓取整个集合子集,然后用谓词过滤检索到的集合,以检查元素是否匹配value1value2

希望能帮助到你。

编辑

如果你按照Eimantasbuild议做一定要创build正确的数组:

 NSNumber valueA = [NSNumber numberWithInt:20]; NSNumber valueB = [NSNumber numberWithInt:90]; NSArray *arr = [NSArray arrayWithObjects:valueA, valueB, nil]; 

除了@ Stuart的回答,你可以使用NSCompoundPredicate来处理你的OR&AND操作。

Obj-C – 或

 // OR Condition // NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"X == 1"]; NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"X == 2"]; NSPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:@[predicate1, predicate2]]; 

Obj-C – 与

 NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"X == 1"]; NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"X == 2"]; NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicate1, predicate2]]; 

Swift – 或者

 let predicate1:NSPredicate = NSPredicate(format: "X == 1") let predicate2:NSPredicate = NSPredicate(format: "Y == 2") let predicate:NSPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: [predicate1,predicate2] ) 

斯威夫特 – 与

 let predicate1:NSPredicate = NSPredicate(format: "X == 1") let predicate2:NSPredicate = NSPredicate(format: "Y == 2") let predicate:NSPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate1,predicate2] ) 

Swift 3 – 或者

  let predicate1 = NSPredicate(format: "X == 1") let predicate2 = NSPredicate(format: "Y == 2") let predicateCompound = NSCompoundPredicate.init(type: .or, subpredicates: [predicate1,predicate2]) 

Swift 3 – 与

  let predicate1 = NSPredicate(format: "X == 1") let predicate2 = NSPredicate(format: "Y == 2") let predicateCompound = NSCompoundPredicate.init(type: .and, subpredicates: [predicate1,predicate2]) 

另一个select是使用一个NSCompoundPredicate(注意和PredicateWithSubpredicates做一个AND,但有几个select使用,这应该比做2search更有效率)

https://developer.apple.com/ library / mac / documentation / Cocoa / Reference / Foundation /