iOS 谓词(NSPredicate)

文档定义

NSPredicate:A definition of logical conditions used to constrain a search either for a fetch or for in-memory filtering.(逻辑条件的定义,用于限制对访存或内存中过滤的搜索。)

谓词代表逻辑条件,可用于过滤对象集合。 虽然直接从NSComparisonPredicate,NSCompoundPredicate和NSExpression的实例创建谓词是很常见的,但是您通常会根据由NSPredicate上的类方法解析的格式字符串来创建谓词。 谓词格式字符串的示例包括:
1. 简单比较,例如成绩==“ 7”或“ Shaffiq”这样的名字
2. 大小写不敏感的查找,例如名称contains [cd]“ itroen”
3. 逻辑运算,例如(名字,例如“ Mark”)或(姓氏,例如“ Adderley”)
4. 时间范围限制,例如{$ YESTERDAY,$ TOMORROW}之间的日期。
5. 关系条件,例如group.name之类的“ work *”
6. 聚合操作,例如@ sum.items.price <1000
有关完整的语法参考,请参阅《谓词编程指南》

谓词的创建

谓词字符串解析器对空格不敏感,对关键字不区分大小写,并且支持嵌套的括号表达式。 它还支持printf样式的格式说明符(例如%x和%@)-请参阅格式化字符串对象。 变量用表示(例如 VARIABLE_NAME)-有关更多详细信息,请参见使用谓词模板创建谓词。
predicateFormat 后面的字符串如何设置可以查看 谓词格式字符串语法

解析器不执行任何语义类型检查。 它会尽力而为地创建合适的表达式,但是(尤其是在替换变量的情况下)可能会生成运行时错误。(确保format字符串是正确的,否则会运行时崩溃)

//初始化方法
public convenience init(format predicateFormat: String, _ args: CVarArg...)

例子:

//like[c]是不区分大小写
let pre = NSPredicate.init(format: "(lastName like[c] %@) AND (birthday > %@)", "abc",NSNumber.init(value: 10))
let result =  pre.evaluate(with: ["lastName":"abc","birthday":11])
print(result)// true

出来通过固定字符串创建谓词以外,还支持 字符串常量,变量和通配符创建谓词
例子:

let pre = NSPredicate.init(format: "lastName like[c] 'S*'")
let result = pre.evaluate(with: ["lastName":"sss"])
print(result)// true

var prefix = "prefix"
var suffix = "suffix"
let pre = NSPredicate.init(format: "lastName like[c] %@", "\(prefix + "*" + suffix)")
let result = pre.evaluate(with: ["lastName":"prefixxxxxxsuffix"])
print(result)// true

/// 数字,bool 类型需要用NSNumberv包裹
let pre = NSPredicate.init(format: "age > %@",NSNumber.init(value: 20))
let result = pre.evaluate(with: ["age":30])
print(result)// true

如果要指定动态属性名称,请在格式字符串中使用%K,如以下片段所示。
由于使用%@将字符串变量替换为格式字符串时,字符串变量用引号引起来,因此您不能使用%@指定动态属性名称,如以下示例所示

var key = "name"
var value = "abc"
let pre = NSPredicate.init(format: "%@ like %@",key,value)
let result = pre.evaluate(with: ["name":"abc"])
print(result)// false

上面这种情况下,谓词格式字符串的值为“name”(注意是带双引号的)
也就是format字符串是 “ “name” like xx 所以匹配结果是false
将key 部分的%@ 换成%K 就能正确匹配

var key = "name"
var value = "abc"
let pre = NSPredicate.init(format: "%K like %@",key,value)
let result = pre.evaluate(with: ["name":"abc"])
print(result)// true

NSComparisonPredicate和NSCompoundPredicate提供方便的方法,使您可以轻松地分别创建复合谓词和比较谓词。 NSComparisonPredicate提供了许多运算符,从简单的相等性测试到自定义函数。详系可以看Creating Predicates Directly in Code

谓词的使用

判断是否符合谓词 可以使用NSPredicate方法evaluateWithObject:并传入要对其评估谓词的对象。也可以将谓词与任何对象类一起使用,但是该类必须支持要在谓词中使用的键的键值编码(key-value coding)。

  1. 在数组中使用谓词
//filtered 是NSArray中的方法,swift中的Array没有这个方法,Array 可以使用filter(isIncluded: (String) throws -> Bool )
let  array = NSArray.init(array: ["Nick", "Ben", "Adam", "Melissa"])
let  pre = NSPredicate.init(format: "SELF beginswith[c] 'b'")
let result = array.filtered(using: pre)
print(result)//[Ben]
  1. Key-Paths 使用 谓词
//KVC的类必须继承自NSObject,变量并且用@objc修饰,否则直接报错
class Person:NSObject{
    @objc var age = 10
}
var person = Person()
let pre = NSPredicate.init(format: "age < %@",NSNumber(value: 20))
let result = pre.evaluate(with: person)
print(result)//true
  1. 筛选nil值
let arr = NSArray.init(array: [["name":"小明"],["name":"小红","age":20]])
let pre = NSPredicate.init(format: "age != nil")
let result = arr.filtered(using: pre)
print(result)
/*
[{
 age = 20;
 name = "\U5c0f\U7ea2";
}]
*/
  1. CoreData 使用谓词
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Employee"
        inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
NSNumber *salaryLimit = <#A number representing the limit#>;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"salary > %@", salaryLimit];
[request setPredicate:predicate];
NSError *error;
NSArray *array = [managedObjectContext executeFetchRequest:request error:&error];
  1. 使用正则表达式
let predicate =  NSPredicate(format: "SELF MATCHES %@" ,"\\d*")
let result = predicate.evaluate(with: "123456789")
print(result)//true

let  predicate = NSPredicate(format: "(name matches %@)&&(age matches %@)" ,"[a-z]*","\\d*")
let  result = predicate.evaluate(with: ["name":"abcd","age":"20"])
print(result)//true

谓词format

  1. 比较符号,都是针对于左边表达式和右边表达式

    • > 大于
    • > =大于等于
    • < 小于
    • <=小于等于
    • ==等于
    • != 或者<> 不等于
    • BETWEEN 介于两者之间,包括上下限
  2. 复合比较

    • && 或者AND 逻辑与
    • || 或者 OR 逻辑或
    • !或者NOT 逻辑非
  3. 字符串比较

    • BEGINSWITH 左边表达式以右边表达式开头
    • CONTAINS 左边表达式包含右边表达式
    • ENDSWITH 左边表达式以右边表达式结尾
    • LIKE 左边表达式和右边表达式相似(简单的正则表达式匹配,?匹配一个字符,*匹配0个或者多个字符)
    • MATCHES 可以实现较为复杂的曾则表达式匹配
    • 用方括号加cd来不区分大小写和变音符号
    • IN 左边的表达式在右边的集合里
    • UTI-CONFORMS-TO该运算符的左侧参数是一个表达式,其计算结果为您要匹配的通用类型标识符(UTI)。 右侧参数是一个表达式,其计算结果为UTI。 如果左侧表达式返回的UTI符合右侧表达式返回的UTI,则比较的结果为TRUE。有关哪些类型符合给定类型的信息,请参见《统一类型标识符参考》中的系统声明的统一类型标识符
    • UTI-EQUALS 该运算符的左侧参数是一个表达式,其计算结果为您要匹配的通用类型标识符(UTI)。 右侧参数是一个表达式,其计算结果为UTI。 如果左侧表达式返回的UTI等于右侧表达式返回的UTI,则比较结果为TRUE。
  4. 集合操作

    • ANY,SOME
      指定以下表达式中的任何元素。例如,任何child.age <18。
    • ALL
      指定以下表达式中的所有元素。例如,所有children.age <18。
    • NONE
      不指定以下表达式中的任何元素。例如,NONE children.age <18。这在逻辑上等效于NOT(ANY …)。
    • IN
      等效于SQL IN操作,左侧必须出现在右侧指定的集合中。
      例如,命名为IN {‘Ben’,‘Melissa’,‘Nick’}。集合可以是数组,集合或字典,如果是字典,则使用其值。
    • array[index]
      指定数组数组中指定索引处的元素。
    • array[FIRST]
      指定数组数组中的第一个元素。
    • array[LAST]
      指定数组数组中的最后一个元素。
    • array[SIZE]
      指定数组数组的大小。
  5. 文字操作
    单引号和双引号产生相同的结果,但它们不会彼此终止。 例如,“ abc”和“ abc”相同,而“a’b’c”等效于a,“ b”,c的以空格分隔的串联。

    • FALSE,NO
      逻辑错误。
    • TRUE ,YES
      逻辑上正确。
    • NULL,NIL
      空值。
    • SELF
      表示被评估的对象。
    • “text”
      字符串。
    • ‘text’
      字符串。
    • 逗号分隔的文字数组
      例如,{‘逗号’,‘分隔’,‘文字’,‘数组’}。
    • 标准整数和定点表示法
      例如1、27、2.71828、19.75。
    • 浮点数与指数
      例如9.2e-5。
    • 0x
      用于表示十六进制数字序列的前缀。
    • 0o
      用于表示八进制数字序列的前缀。
    • 0b
      用于表示二进制数字序列的前缀。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章