NSPredicate中的多个条件

13
如何在 NSPredicate 中使用多个条件?我正在使用以下代码,但返回的数组中没有任何内容。
NSPredicate *placePredicate = [NSPredicate predicateWithFormat:@"place CONTAINS[cd] %@ AND category CONTAINS[cd] %@ AND ((dates >= %@) AND (dates <= %@)) AND ((amount >= %f) AND (amount <= %f))",placeTextField.text,selectedCategory,selectedFromDate,selectedToDate,[amountFromTextField.text floatValue],[amountToTextField.text floatValue]];

NSArray *placePredicateArray = [dataArray filteredArrayUsingPredicate:placePredicate];

NSLog(@"placePredicateArray %@", placePredicateArray);

有时候数量和类别可能为空。我应该如何构建NSPredicate

3个回答

30
你可以使用其他的 `NSPredicate` 对象和 `NSCompoundPredicate` 类来构建你的 `placesPredicate`。
类似这样:
NSPredicate *p1 = [NSPredicate predicateWithFormat:@"place CONTAINS[cd] %@", placeTextField.text];
NSPredicate *p2 = [NSPredicate predicateWithFormat:@"category CONTAINS[cd] %@", selectedCategory];
NSPredicate *p3 = [NSPredicate predicateWithFormat:@"(dates >= %@) AND (dates <= %@)", selectedFromDate,selectedToDate];
NSPredicate *p4 = [NSPredicate predicateWithFormat:@"(amount >= %f) AND (amount <= %f)", [amountFromTextField.text floatValue],[amountToTextField.text floatValue]]; 

NSPredicate *placesPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[p1, p2, p3, p4]];

如果你缺少了分类,你可以使用一个虚拟的 YES 谓词来代替它:

NSPredicate *p2;
if (selectedCategory) {
    p2 = [NSPredicate predicateWithFormat:@"category CONTAINS[cd] %@", selectedCategory];
} else {
    p2 = [NSPredicate predicateWithBool:YES]
}

但是如何从NSPredicate获取数组? - Prerna chavan
如果您需要获取用于创建复合谓词的谓词数组,请使用NSCompoundPredicatesubpredicates属性。您还应该仔细查看@DRVic的答案-他在动态地创建谓词数组时更加高效,因为他不需要包含任何“YES”谓词,但这意味着您不知道子谓词数组中哪个谓词很容易找到其索引。 - deanWombourne
NSCompoundPredicate实例将具有子谓词数组属性,这是显而易见的。将普通的NSPredicate转换为数组是没有意义的! - deanWombourne

13

我倾向于逐一处理这个问题。也就是说,

placePredicate = [NSPredicate predicateWithFormat:@"place CONTAINS[cd] %@",placeTextField.text];
NSMutableArray *compoundPredicateArray = [ NSMutableArray arrayWithObject: placePredicate ]; 

if( selectedCategory != nil ) // or however you need to test for an empty category
    {
    categoryPredicate = [NSPredicate predicateWithFormat:@"category CONTAINS[cd] %@",selectedCategory];
    [ compoundPredicateArray addObject: categoryPredicate ];
    }

// and similarly for the other elements.  
请注意,即使我知道没有谓词(或任何其他东西),我也不会将类别的谓词甚至放入数组中。
// Then
    NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:
                                  compoundPredicateArray ];

如果我打算经常这样做,我不会使用格式化方法,而是保留构建块并只更改每次使用之间发生变化的部分。


+1 对这条评论的赞同“// 或者你需要如何测试空类别”真的帮了我.. 谢谢! :) - 0yeoj

0
Suppose a class Person with attributes "name", "age", "income"

"personArray" is array of class Person

NSPredicate *mypredicate = [NSPredicate predicateWithBlock:^BOOL(personObj Person, NSDictionary *bindings) {
     NSNumber *age = personObj.age;
     String *name = personObj.name;
     NSNumber *income = personObj.income
     BOOL result = (age > 20 && name == "Stack" && income >40000);
     return result;
}];

NSArray *filteredArray = [personArray filteredArrayUsingPredicate: mypredicate];

您可以阅读这篇文章了解更多Array Filter Using Blocks的内容

在Swift中

let filterArray = personArray.filter
            { person in
           let age = personObj.age;
           let name = personObj.name;
           let income = personObj.income
           BOOL result = (age > 20 && name == "Stack" && income >40000);
          return result;
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接