Objective-C中的NSPredicate
編寫軟件時,經常需要獲取一個對象集合,并通過某些已經條件計算該集合的值。你需要保留符合某個條件的對象,刪除那些不滿足條件的對象,從而提供一些有意義的對象。
在使用軟件iPhoto的過程中,經常會看到這種現象,如果通知iPhoto僅顯示等級為三星級或三星級以上的圖片,則指定的條件為“照片的等級必須為三星級或三星級以上”。這樣,所有照片都需要經過該過濾器過濾。滿足條件的對象通過了過濾器,而其他對象被篩除了。最后,iPhoto將顯示出所有高質量的圖片。
Cocoa提供了一個名為NSPredicate的類,它用于指定過濾器的條件。可以創建NSPredicate對象,通過該對象準確地描述所需的條件,對每個對象通過謂詞進行篩選,判斷它們是否與條件相匹配。這里的“謂詞”通常用在數學和計算機科學概念中,表示計算真值或假值的函數。
Cocoa用NSPredicate描述查詢的方式,原理類似于在數據庫中進行查詢。可以在數據庫風格的API中使用NSPredicate類,例如Core Data和Spotlight。可以將NSPredicate看成另一種間接操作方式。例如,如果需要查詢滿足條件的機器人,可以使用謂詞對象進行檢查,而不必使用代碼進行顯示查詢。通過交換謂詞對象,可以使用通用代碼對數據進行過濾,而不必對相關條件進行硬編碼。
創建
1)方式一
創建許多對象,并將它們組合起來。如果正在構建通用用戶接口來指定查詢,采用這種方式比較簡單。
2)方式二
查詢代碼中的字符串。
Car *car;
Car = makeCar(@"Herbie", @"Honda", @"CRX", 1984, 2, 110000, 58);
[garage addCar:car];
/*構建的汽車:品牌為Herbie,型號為雙門1984Honda CRX,馬力引擎為58,已經行駛距離為110000英里*/
/*創建謂詞*/
NSPredicate *predicate;
predicate = [NSPredicate predicateWithFormat:@"name == 'Herbie'"];
計算謂詞
BOOL match = [predicate evaluateWithObject:car];
NSLog(@"%s",(match) ? "YES":"NO");
另外一個謂詞:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"engine.horsepower >150"];
/*查看車庫中哪些車的功率最大,可以循環測試每個汽車的謂詞*/
NSArray *cars = [garage cars];
for(Car *car in cars){
if([predicate evaluateWithObject:car]){
NSLog(@"%@", car.name);
}
}
過濾器
如果我們不必像上文那樣編寫for循環和if語句,這有什么不好?實際上,某些類別將謂詞過濾方法添加到了Cocoa集合類中。 -filteredArrayUsingPredicate: 是NSArray數組中的一種類別方法,它將循環過濾數組內容,根據謂詞計算每個對象的值,并將值為YES的對象累積到將被返回的新數組中:
NSArray *results;
results = [cars filteredArrayUsingPredicate:predicate];
NSLog(@"%@",results);
假如有一個可變數組,你需要剔除不屬于該數組的所有項目:
NSMutableArray *carsCopy = [cars mutableCopy];
[carsCopyfilterUsingPredicate:predicate];
格式說明符
資深編程人員都知道,硬編碼并非好方法,因此,我們可以通過格式符構建謂詞:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"engine.horsepower > %d", 50];
運算符
NSPredicate的格式字符串包含大量不同的運算符。
1)比較和邏輯運算符
謂詞字符串語法支持C語言中一些常用的運算符,例如等號運算符==和=。
不等號運算符具有各種形式:
>:大于
>=和=>:大于或等于
<:小于
<=和=<:小于或等于
!=和<>:不等于
此外,謂詞字符串語法還支持括號表達式和AND、OR、NOT邏輯運算符或者C樣式的等效表達式&&、||和!。
2)數組運算符
謂詞字符串“(engine.horsepower> 50) OR (engine.horsepower < 200)”是一種十分常見的模式。等效于:
predicate= [NSPredicate predicateWithFormat:@"engine.horespower BETWEEN {50,200}"];
花括號表示數組,BETWEEN將數組中第一個元素看成是數組的下界,第二個元素看成是數組的上界。
NSArray *betweens = [NSArray arrayWithObjects:[NSNumber numberWithInt:50],[NSNumber numberWithInt:200], nil];
predicate = [NSPredicate predicateWithFormat:@"engine.horsepower BETWEEN %@",betweens];
數組不僅僅用來指定某個區間的端點值。你可以使用IN運算符查找數組中是否含有某個特定值。
predicate = [NSPredicate predicateWithFormat:@"name IN {'Herbie', 'Snugs', 'Badger','Flap'}"];
來自:http://charsdavy.github.io/2017/03/28/objc-NSPredicate/