字符串常量、变量和通配符
字符串常量必须用引号包裹起来,用单引号或双引号都是可以的,如果你用%@来进行参数替换(例如firstName like %@
),引号会自动添加,如果你用的是字符串常量,那你必须自己用引号包裹起来:
NSPredicate* predicate = [NSPredicate predicateWithFormat: @"lastName like[c] 'S*'"];
NSPredicate* predicate = [NSPredicate predicateWithFormat: @"lastName like[c] "S*""];
在使用通配符时必须考虑引号的问题,你应该把通配符添加到一个预定义的变量中来进行参数替换:
NSString* prefix = @"prefix";
NSString* suffix = @"suffix";
NSPredicate* predicate = [NSPredicate predicateWithFormat: @"SELF like[c] %@",[[prefix stringByAppendingString: @"*"] stringByAppendingString: suffix]];
BOOL ok = [predicate evaluateWithObject: @"prefixxxxxxxsuffix"];
下面则是一个错误的例子:
predicate = [NSPredicate predicateWithFormat: @"SELF like[c] %@*%@",prefix,suffix];
ok = [predicate evaluateWithFormat: @"prefixxxxxsuffix"];
直接用代码来创建的NSPredicate
Objective-C:
NSExpression *lhs = [NSExpression expressionForKeyPath:@"revenue"]; NSExpression *greaterThanRhs = [NSExpression expressionForConstantValue:[NSNumber numberWithInt:1000000]]; NSPredicate *greaterThanPredicate = [NSComparisonPredicate predicateWithLeftExpression:lhs rightExpression:greaterThanRhs modifier:NSDirectPredicateModifier type:NSGreaterThanOrEqualToPredicateOperatorType options:0]; NSExpression *lessThanRhs = [NSExpression expressionForConstantValue:[NSNumber numberWithInt:100000000]]; NSPredicate *lessThanPredicate = [NSComparisonPredicate predicateWithLeftExpression:lhs rightExpression:lessThanRhs modifier:NSDirectPredicateModifier type:NSLessThanPredicateOperatorType options:0]; NSCompoundPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates: @[greaterThanPredicate,lessThanPredicate]];
Swift:
let lhs = NSExpression(forKeyPath: "revenue")
let greaterThanRhs = NSExpression(forConstantValue: "张三")
let greaterPredicate = NSComparisonPredicate(leftExpression: lhs,rightExpression: greaterThanRhs,modifier: .DirectPredicateModifier,type: .BeginsWithPredicateOperatorType,options: .CaseInsensitivePredicateOption)
let lessThanRhs = NSExpression(forConstantValue: 1000000000000)
let lessThanPredicate = NSComparisonPredicate(leftExpression: lhs,rightExpression: lessThanRhs,type: .LessThanOrEqualToPredicateOperatorType,options: .CaseInsensitivePredicateOption)
let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [greaterPredicate,lessThanPredicate])
使用Predicate
使用NSPredicate的evaluateWithObject方法并传入要查询的数据,这个方法会返回一个布尔值:
Objective-C:
NSPredicate* predicate = [NSPredicate predicateWithFormat: @"SELF in %@",@[@"Stig",@"Shaffig",@"Chris"]];
BOOL result = [predicate evaluateWithObject: @"Shaffig"];
Swift:
let predicate = NSPredicate(format: "SELF in %@",["Stig","Shaffig","Chris"]) // SELF IN {"Stig","Chris"}
let result = predicate.evaluateWithObject("Stig") // true
在数组中使用Predicate
Objective-C:
NSMutableArray* array = [NSMutableArray arrayWithObjects: @"Nick",@"Ben",@"Adam",@"Melissa",nil];
NSPredicate* sPredicate - [NSPredicate predicateWithFormat: @"SELF contains[c] 'e'"];
[array filterUsingPredicate: sPredicate];
在predicate中传入key-path
NSString* departmentName = ...;
NSPredicate* predicate = [NSPredicate predicateWithFormat: @"department.name like %@",departmentName];
如果你使用的是一对多的关系,那么predicate的构造会有些许不同:
NSPredicate* predicate = [NSPredicate predicateWithFormat: @"ANY employees.firtName like 'Matthew'"];
NSPredicate* predicate = [NSPredicate predicateWithFormat: @"ANY employees.salary > %f",salary];
使用空值
comparison predicate不会匹配任何的null值,除非nil或者NSNull,也就是($value == nil)。看一下下面的例子:
NSString* firstName = @"Ben";
NSArray* array = @[@{@"lastName" : @"Turner"},@{@"firstName" : @"Ben",@"lastName" : @"Ballard",@"birthday" : [NSDate dateWithString: @"1972-03-24 10:45:32 +0600"]}
];
NSPredicate* predicate = [NSPredicate predicateWithFormat:@"firstName like %@",firstName];
NSArray* filteredArray = [array filteredArrayUsingPredicate:predicate];
NSLog(@"%@",filteredArray);
predicate 匹配了包含firstName 键的值,却没匹配上不包含这个键的值,下面的例子是同样的道理:
NSDate* referenceDate = [NSDate dateWithTimeIntervalSince1970:0];
predicate = [NSPredicate predicateWithFormat:@"birthday > %@",referenceDate];
filteredArray = [array filteredArrayUsingPredicate:predicate];
NSLog(@"%@",filteredArray);
如果你想要匹配null值,你就得添加一条额外的对比:
predicate = [NSPredicate predicateWithFormat:@"(firstName == %@) || (firstName == nil)"];
filteredArray = [array filteredArrayUsingPredicate:predicate];
NSLog(@"%@",filteredArray);
在 CoreData 上使用predicate
下面的例子展示了在CoreData中使用NSPredicate进行查询:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [[NSEntityDescription entityForName: @"Employee"] inManagedObjectContext: managedObjectContext];
[request setEntity: entity];
NSNumber *salaryLimit = @2000;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"salary > %@",salaryLimit];
[request setPredicate: predicate];
NSError *error;
NSArray *array = [managedObjectContext executeFetchRequest: request error: &error];