再次需要更多帮助来构建我的NSPredicates :(
Category
{
name:string
subs<-->>SubCategory
}
SubCategory
{
name:string
numbervalue:NSNumber
}
我想知道如何使用 AND 和 OR 创建谓词。
例如,我想返回名称为==“category_name”的每个类别,其中还有一个子类别,其值为“valueA” OR “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)使用此结果导致整个集合被返回,即使集合中只有1个项目具有该值。
predicate=[NSPredicate predicateWithFormat:@"(ANY subs.numbervalue IN %@)",arr];
2)使用它会导致同样的问题,即使只有1个项目匹配,也会返回集合中的每个项目。
predicate=[NSPredicate predicateWithFormat:@"((SUBQUERY(subs, $x, $x.numbervalue == %@ or $x.numbervalue == %@).@count > 0)", value1, value2];
同样使用最简单的版本会导致同样的问题......我之前没有注意到这一点。
NSPredicate *predicate=[NSPredicate predicateWithFormat@"(ANY subs.numbervalue==%@ ,valueA];
所以我认为我的问题缩小了。
类别是实体。 SubCategory是一个实体。
类别与SubCategory有一对多的关系,并表示为SubCategory的NSSet。
每个SubCategory都有一个名为numbervalue的属性。
编辑3
要测试我有2个分类。 两个类别都有10个潜艇,每个潜艇的数值为1 -10;
使用此代码返回两个类别以及每个类别的所有10个子类。
预期结果是两个类别都返回,每个类别只有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();
}
答案 0 :(得分:71)
除了@Stuart的答案,你可以使用NSCompoundPredicate作为你的OR&amp;和这样的操作。
Obj-C - 或
// OR Condition //
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"X == 1"];
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"X == 2"];
NSPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:@[predicate1, predicate2]];
Obj-C - AND
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"X == 1"];
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"X == 2"];
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicate1, predicate2]];
斯威夫特 - 或
let predicate1:NSPredicate = NSPredicate(format: "X == 1")
let predicate2:NSPredicate = NSPredicate(format: "Y == 2")
let predicate:NSPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: [predicate1,predicate2] )
Swift - AND
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 - AND
let predicate1 = NSPredicate(format: "X == 1")
let predicate2 = NSPredicate(format: "Y == 2")
let predicateCompound = NSCompoundPredicate.init(type: .and, subpredicates: [predicate1,predicate2])
答案 1 :(得分:34)
我将使用SUBQUERY
执行以下操作。
[NSPredicate predicateWithFormat@"(name == %@) AND (SUBQUERY(subs, $x, $x.numbervalue == %@ or $x.numbervalue == %@).@count > 0)", @"aname", value1, value2];
试试并告诉我。
另一种解决方案可能是获取整个集合subs
,然后使用谓词过滤检索到的集合,以检查元素是否与value1
或value2
匹配。
希望它有所帮助。
修改强>
如果您按照 Eimantas 建议,请确保创建正确的数组:
NSNumber valueA = [NSNumber numberWithInt:20];
NSNumber valueB = [NSNumber numberWithInt:90];
NSArray *arr = [NSArray arrayWithObjects:valueA, valueB, nil];
答案 2 :(得分:1)
另一种选择是使用NSCompoundPredicate(注意andPredicateWithSubpredicates会执行AND,但是有一些选项可以使用,这应该比进行2次搜索更有效)
答案 3 :(得分:0)
这是您可以执行的操作:
SWIFT 4.x-和
let p0 = NSPredicate(format: "X == 1")
let p1 = NSPredicate(format: "Y == 2")
fetchRequest.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [p0, p1])
SWIFT 4.x-或
let p0 = NSPredicate(format: "X == 1")
let p1 = NSPredicate(format: "Y == 2")
fetchRequest.predicate = NSCompoundPredicate(orPredicateWithSubpredicates: [p0, p1])
SWIFT 4.x-不
let p0 = NSPredicate(format: "X == 1")
let p1 = NSPredicate(format: "Y == 2")
fetchRequest.predicate = NSCompoundPredicate(notPredicateWithSubpredicates: [p0, p1])
示例
这是我的代码之一的示例,我在其中查找uid并进行同步:
let p0 = NSPredicate(format: self.uid + " = '" + uid + "'")
let p1 = NSPredicate(format: self.sync + " = %@", NSNumber(value: true as Bool))
fetchRequest.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [p0, p1])