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
      用於表示二進制數字序列的前綴。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章