Origheart

谓词

  • NSPredicate是Foundation框架中的一个类。
  • 作用:指定数据被获取和过滤的方式。提供了类似于自然语言一样定义一个集合被搜寻的逻辑条件。

为了证明NSPredicate的强大功能,先写一个Person类,做准备工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Person: NSObject {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
super.init()
}
override var description: String {
return "name: \(self.name), age: \(self.age)"
}
}
var colleagues = NSMutableArray()
colleagues.addObject(Person(name: "Arthur", age: 45))
colleagues.addObject(Person(name: "Michael", age: 23))
colleagues.addObject(Person(name: "Kenny", age: 25))
colleagues.addObject(Person(name: "Bella", age: 24))
colleagues.addObject(Person(name: "Vincent", age: 36))
colleagues.addObject(Person(name: "Adolph", age: 39))

基本使用

找出年龄为24岁的人:

1
2
let predicateByAge = NSPredicate(format: "age == 24")
let result = colleagues.filteredArrayUsingPredicate(predicateByAge)

参数可以传入:

1
2
3
let age = NSNumber(int: 25)
let predicateByPassAge = NSPredicate(format: "age == %@", age)
let result1 = colleagues.filteredArrayUsingPredicate(predicateByPassAge)

也可传入要对比的属性,这里是age. 属性的key:

1
2
let pridicateByAge1 = NSPredicate(format: "%K == %@", "age", NSNumber(int: 36))
let result2 = colleagues.filteredArrayUsingPredicate(pridicateByAge1)

指定通配的变量,这里用24来替代age:

1
2
let pridicateByAge2 = NSPredicate (format: "age == $age")
let result3 = colleagues.filteredArrayUsingPredicate(pridicateByAge2.predicateWithSubstitutionVariables(["age": NSNumber(int: 24)]))

语法小结

  • 使用%@对应数字,字符串,日期的替代值
  • 使用%K对应要比较的属性,也就是KVC中的key
  • 使用$变量名来表示通配的变量,然后predicateWithSubstitutionVariables来决定具体的变量值

基本比较

找出年龄大于40岁的同事:

1
2
let predicateAgeOver40 = NSPredicate(format: "age > 40")
let boss = colleagues.filteredArrayUsingPredicate(predicateAgeOver40)

找出年龄在22岁~35岁的人:

1
2
3
4
let minAge = NSNumber(int: 22)
let maxAge = NSNumber(int: 35)
let predicateByAge3 = NSPredicate(format: "age BETWEEN {%@, %@}", minAge, maxAge)
let result4 = colleagues.filteredArrayUsingPredicate(predicateByAge3)

语法小结

  • > 大于
  • >= 大于等于
  • < 小于
  • <= 小于等于
  • == 等于
  • != 或者 <> 不等于
  • BETWEEN 介于两者之间,包括上下限

复合比较

  • && 或者AND 逻辑与
  • || 或者 OR 逻辑或
  • !或者NOT 逻辑非
1
2
let predicateByCompare = NSPredicate(format: "age < 30 OR age >= 40")
let result5 = colleagues.filteredArrayUsingPredicate(predicateByCompare)

字符串比较

  • BEGINSWITH 左边表达式以右边表达式开头
  • CONTAINS 左边表达式包含右边表达式
  • ENDSWITH 左边表达式以右边表达式结尾
  • LIKE 左边表达式和右边表达式相似(简单的正则表达式匹配,?匹配一个字符,*匹配0个或者多个字符)
  • MATCHES 可以实现较为复杂的正则表达式匹配
  • 用方括号加cd来不区分大小写和变音符号
  • IN 左边的表达式在右边的集合里

找出名字以“A”开头的同事:

1
2
let pridivateByName1 = NSPredicate(format: "name BEGINSWITH %@", "A")
let result6 = colleagues.filteredArrayUsingPredicate(pridivateByName1)

名字里包含in,不区分大小写,并且年龄大于等于24:

1
2
let pridivateByName2 = NSPredicate(format: "name CONTAINS %@ && age >= %@", "in", NSNumber(int: 24))
let result7 = colleagues.filteredArrayUsingPredicate(pridivateByName2)

复合正则表达式T[a-z]*k:

1
2
let privatedivateByName3 = NSPredicate(format: "name MATCHES 'T[a-z]*k'")
let result8 = colleagues.filteredArrayUsingPredicate(privatedivateByName3)

名字是两者中的一个:

1
2
let privatedivateByName4 = NSPredicate(format: "name IN {'Bella', 'Jack Tomphon'}")
let result9 = colleagues.filteredArrayUsingPredicate(privatedivateByName4)

基于Block的谓词

基于Block能够灵活的定制谓词,这里简单的Block定义age > 24:

1
2
3
4
5
6
7
8
9
10
let blockPredicate = NSPredicate { (person: AnyObject!, _) -> Bool in
var result = false
if let castResult = person as? Person {
if castResult.age > 24 {
result = true
}
}
return result
}
let result10 = colleagues.filteredArrayUsingPredicate(blockPredicate)

Array使用谓词参考:

StackOverFlow