NSPredicate 实践

iOS中提供了一套很好的类似SQL一般的内存数据操作方法集:NSPredicate(类似C#中的LINQ),用于数据集的读取和过滤,支持正则表达式。


Image source

NSPredicate主要应用于CoreData和数组类NSArray, NSmutableArray中,NSSetNSMutableSet也可以用这个类筛选.

1
2
3
4
5
# NSArray
func filteredArrayUsingPredicate(predicate: NSPredicate) -> [AnyObject]
# NSMutableArray
func filterUsingPredicate(predicate: NSPredicate)

简单查询示例代码:代码来自

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Person: NSObject {
let firstName: String
let lastName: String
let age: Int
init(firstName: String, lastName: String, age: Int) {
self.firstName = firstName
self.lastName = lastName
self.age = age
}
override var description: String {
return "\(firstName) \(lastName)"
}
}
let alice = Person(firstName: "Alice", lastName: "Smith", age: 24)
let bob = Person(firstName: "Bob", lastName: "Jones", age: 27)
let charlie = Person(firstName: "Charlie", lastName: "Smith", age: 33)
let quentin = Person(firstName: "Quentin", lastName: "Alberts", age: 31)
let people = [alice, bob, charlie, quentin]
let bobPredicate = NSPredicate(format: "firstName = 'Bob'")
let smithPredicate = NSPredicate(format: "lastName = %@", "Smith")
let thirtiesPredicate = NSPredicate(format: "age >= 30")
(people as NSArray).filteredArrayUsingPredicate(bobPredicate)
// ["Bob Jones"]
(people as NSArray).filteredArrayUsingPredicate(smithPredicate)
// ["Alice Smith", "Charlie Smith"]
(people as NSArray).filteredArrayUsingPredicate(thirtiesPredicate)
// ["Charlie Smith", "Quentin Alberts"]

NSPredicate 筛选

NSPredicate 中支持的关键词和条件符:

1、>, <, >=, <=, =, != 比较运算符

1
2
3
# 这里的字符串要用单引号
let bobPredicate = NSPredicate(format: "firstName = 'Bob'")
let thirtiesPredicate = NSPredicate(format: "age >= 30")

2、字符串操作(包含):BEGINSWITHENDSWITHCONTAINS

1
2
3
"firstName BEGINSWITH[cd] 'B'"
"firstName ENDSWITH[c] 'b'"
"firstName CONTAINS[d] 'o'"
  • [c] 不区分大小写
  • [d] 不区分发音符号即没有重音符号
  • [cd] 既不区分大小写,也不区分发音符号。

3、范围:INBWTEEN

1
2
"age BWTEEN {20, 50}"
"age IN [20, 31]"

4、SELF

这个只针对字符数组起作用。

1
2
var arr = ["Bob", "Alice", @"Jones"]
"SELF='Jones'"

5、通配符:LIKE

LIKE 使用?表示一个字符,*表示多个字符,也可以与c、d 连用。

1
2
"firstName LIKE '?o?'" // 匹配三个字符,且中间字符为o
"car.name LIKE '*ob'" // 匹配任意长度,且未尾以ob结尾的字符串

6、正则表达式:MATCHES

1
2
3
4
5
6
7
NSString *regex = @"^B.+b$"; //以E 开头,以e 结尾的字符。
NSPredicate *pre= [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
if([pre evaluateWithObject: @"Employee"]){
NSLog(@"matches YES");
}else{
NSLog(@"matches NO");
}

7、逻辑运算符:ANDORNOT

1
"firstName = 'John' AND lastName = 'Smith'"

多重筛选

有些筛选条件很复杂,其中小的项目又可以在多个大的条件中共用,就可以试下NSCompoundPredicate,它可以代替OR,AND来进行多个NSPredicate对象的组合:

1
2
3
4
5
let bobPredicate = NSPredicate(format: "firstName = 'Bob'")
let thirtiesPredicate = NSPredicate(format: "age >= 30")
let andPredicate = NSCompoundPredicate.andPredicateWithSubpredicates([bobPredicate!, thirtiesPredicate!])
let orPredicate = NSCompoundPredicate.orPredicateWithSubpredicates([bobPredicate!, thirtiesPredicate!])

NSPredicate 匹配

NSPredicate还可以通过evaluateWithObject(_:)方法来判断匹配是否符合。

1
2
3
4
5
6
7
8
let bobPredicate = NSPredicate(format: "firstName = 'Bob'")
let match: Bool = bobPredicate!.evaluateWithObject(bob)
# 名字是否以b结尾
var name = "Bob"
var regex = "^B.+b$"
NSPredicate *bobPredicate = NSPredicate(format: "firstName MATCHES %@", regex)
let match: Bool = bobPredicate!.evaluateWithObject(name)

REF::