iOS-謂詞的使用詳解

?建議收藏棚菊,用到時候一查就明白了 --xx_cc.

一翠拣、NSPredicate基本語句

只要我們使用謂詞(NSPredicate)都需要為謂詞定義謂詞表達(dá)式,而這個表達(dá)式必須是一個返回BOOL的值按摘。

謂詞表達(dá)式由表達(dá)式朗徊、運(yùn)算符和值構(gòu)成。

1.比較運(yùn)算符

比較運(yùn)算符如下

=娜庇、==:判斷兩個表達(dá)式是否相等塔次,在謂詞中=和==是相同的意思都是判斷方篮,而不是賦值

NSNumber *testNumber = @123;
  NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF = 123"];
  if ([predicate evaluateWithObject:testNumber]) {
      NSLog(@"testString:%@", testNumber);
  }

我們可以看到輸出的內(nèi)容為:

2016-01-07 11:12:27.281 PredicteDemo[4130:80412] testString:123

<=:判斷右邊表達(dá)式的值是否小于或等于右邊表達(dá)式的值

>=:判斷左邊表達(dá)式的值是否大于右邊表達(dá)式的值

< :判斷左邊表達(dá)式的值是否小于右邊表達(dá)式的值

> :判斷左邊表達(dá)式的值是否大于右邊表達(dá)式的值

!= :判斷兩個表達(dá)式是否不相等

BETWEENBETWEEN表達(dá)式必須滿足表達(dá)式 BETWEEN {下限,上限}的格式励负,要求該表達(dá)式必須大于或等于下限藕溅,并小于或等于上限

NSNumber *testNumber = @123;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF BETWEEN {100, 200}"];
  if ([predicate evaluateWithObject:testNumber]) {
      NSLog(@"testString:%@", testNumber);
  } else {
      NSLog(@"不符合條件");
  }

輸出結(jié)果為:

2016-06-22 17:45:02.802 NSPredicate[4579:1144449] testString:123

2.邏輯運(yùn)算符

AND、&& :邏輯與继榆,要求兩個表達(dá)式的值都為YES時巾表,結(jié)果才為YES。

NSArray *testArray = @[@1, @2, @3, @4, @5, @6];
  NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF > 2 && SELF < 5"];
  NSArray *filterArray = [testArray filteredArrayUsingPredicate:predicate];
  NSLog(@"filterArray:%@", filterArray);

輸出結(jié)果為:

2016-06-22 17:56:36.957 NSPredicate[4731:1162773] filterArray:(
    3,
    4
)

OR略吨、|| :邏輯或攒发,要求其中一個表達(dá)式為YES時,結(jié)果就是YES

NOT晋南、 ! :邏輯非,對原有的表達(dá)式取反

3.字符串比較運(yùn)算符

BEGINSWITH:檢查某個字符串是否以指定的字符串開頭(如判斷字符串是否以a開頭:BEGINSWITH 'a')

 NSString *string = @"abcdefg";
 NSPredicate *predicate = [NSPredicate predicateWithFormat:@" %@ BEGINSWITH 'a'",string];
 if ([predicate evaluateWithObject:string]) {
     NSLog(@"string:%@", string);
 }

輸出結(jié)果為:

2016-06-22 18:09:18.922 NSPredicate[4902:1183020] string:abcdefg```
`ENDSWITH` :檢查某個字符串是否以指定的字符串結(jié)尾

`CONTAINS` :檢查某個字符串是否包含指定的字符串

`LIKE` :檢查某個字符串是否匹配指定的字符串模板羔砾。其之后可以跟`?`代表一個字符和`*`代表任意多個字符兩個通配符负间。比如`"name LIKE '*ac*'"`,這表示name的值中包含`ac`則返回YES姜凄;`"name LIKE '?ac*'"`政溃,表示name的第2、3個字符為`ac`時返回YES态秧。

`MATCHES`:檢查某個字符串是否匹配指定的正則表達(dá)式董虱。雖然正則表達(dá)式的執(zhí)行效率并不高,但其功能是最強(qiáng)大的申鱼,也是我們最常用的愤诱。

>注: 字符串比較都是區(qū)分大小寫和重音符號的。如:café和cafe是不一樣的捐友,Cafe和cafe也是不一樣的淫半。如果希望字符串比較運(yùn)算不區(qū)分大小寫和重音符號,請在這些運(yùn)算符后使用`[c]`匣砖,`[d]`選項科吭。其中`[c]`是不區(qū)分大小寫,`[d]`是不區(qū)分重音符號猴鲫,其寫在字符串比較運(yùn)算符之后对人,比如:`"name LIKE[cd] 'cafe'"`,那么不論`name`是cafe拂共、Cafe還是café上面的表達(dá)式都會返回YES牺弄。

###4.集合運(yùn)算符

`ANY、SOME` :集合中任意一個元素滿足條件匣缘,就返回YES猖闪。

`ALL` :集合中所有元素都滿足條件鲜棠,才返回YES。

`NONE` :集合中沒有任何元素滿足條件就返回YES培慌。如:`NONE person.age<18`豁陆,表示person集合中所有元素的age>=18時,才返回YES吵护。

`IN`:等價于SQL語句中的IN運(yùn)算符盒音,只有當(dāng)左邊表達(dá)式或值出現(xiàn)在右邊的集合中才會返回YES。我們通過一個例子來看一下

NSArray *filterArray = @[@"ab", @"abc"];
NSArray *array = @[@"a", @"ab", @"abc", @"abcd"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (SELF IN %@)", filterArray];
NSLog(@"%@", [array filteredArrayUsingPredicate:predicate]);

代碼的作用是將array中和filterArray中相同的元素去除馅而,輸出為:

2016-06-22 18:11:15.785 NSPredicate[4926:1185775] (
a,
abcd
)

`array[index]`:返回array數(shù)組中index索引處的元素

`array[FIRST]`:返回array數(shù)組中第一個元素

`array[LAST]`:返回array數(shù)組中最后一個元素

`array[SIZE]`:返回array數(shù)組中元素的個數(shù)

###5.直接量

在謂詞表達(dá)式中可以使用如下直接量

`FALSE祥诽、NO`:代表邏輯假

`TRUE、YES`:代表邏輯真

`NULL瓮恭、NIL`:代表空值

`SELF` :代表正在被判斷的對象自身

` "string"或'string'`:代表字符串

`數(shù)組`:和c中的寫法相同雄坪,如:`{'one', 'two', 'three'}`。

`數(shù)值`:包括整數(shù)屯蹦、小數(shù)和科學(xué)計數(shù)法表示的形式

`十六進(jìn)制數(shù)`:0x開頭的數(shù)字

`八進(jìn)制`:0o開頭的數(shù)字

`二進(jìn)制`:0b開頭的數(shù)字

###6.保留字

下列單詞都是保留字(不論大小寫)

>AND维哈、OR、IN登澜、NOT阔挠、ALL、ANY脑蠕、SOME购撼、NONE、LIKE谴仙、CASEINSENSITIVE迂求、CI、MATCHES晃跺、CONTAINS锁摔、BEGINSWITH、ENDSWITH哼审、BETWEEN谐腰、NULL、NIL涩盾、SELF十气、TRUE、YES春霍、FALSE砸西、NO、FIRST、LAST芹枷、SIZE衅疙、ANYKEY、SUBQUERY鸳慈、CAST饱溢、TRUEPREDICATE、FALSEPREDICATE

注:雖然大小寫都可以走芋,但是更推薦使用大寫來表示這些保留字

##二绩郎、謂詞的用法

###1.定義謂詞

一般我們使用下列方法來定義一個謂詞

NSPredicate *predicate = [NSPredicate predicateWithFormat:<#(nonnull NSString *), ...#>];


下面我們通過幾個簡單的例子來看看它該如何使用:

首先我們需要定義一個模型,因為示例中需要用到它

PersonModel.h

import typedef NS_ENUM(NSInteger, PersonSex) {

PersonSexMale = 0,
PersonSexFamale

};

@interface PersonModel : NSObject
/** NSString 姓名 /
@property (nonatomic, copy) NSString name;
/
NSUInteger 年齡 /
@property (nonatomic, assign) NSUInteger age;
/
* ZLPersonSex 性別 */
@property (nonatomic, assign) PersonSex sex;

  • (instancetype)personWithName:(NSString *)name age:(NSUInteger)age sex:(PersonSex)sex;

@end

下面讓我們進(jìn)入正題

例一:(最簡單的使用)
PersonModel *sunnyzl = [PersonModel personWithName:@"sunnyzl" age:29 sex:PersonSexMale];
PersonModel *jack = [PersonModel personWithName:@"jack" age:22 sex:PersonSexMale];
//  首先我們來看一些簡單的使用
//  1.判斷姓名是否是以s開頭的翁逞,上面已經(jīng)用過BEGINSWITH方法肋杖,這里用LIKE
NSPredicate *pred1 = [NSPredicate predicateWithFormat:@"name LIKE 's*'"];
NSLog(@"sunnyzl:%d, jack:%d", [pred1 evaluateWithObject:sunnyzl], [pred1 evaluateWithObject:jack]);
//  輸出為:sunnyzl:1, jack:0

//  2.判斷年齡是否大于25
NSPredicate *pred2 = [NSPredicate predicateWithFormat:@"age > 25"];
NSLog(@"sunnyzl的年齡是否大于25:%d, jack的年齡是否大于25:%d", [pred2 evaluateWithObject:sunnyzl], [pred2 evaluateWithObject:jack]);
//  輸出為:sunnyzl的年齡是否大于25:1, jack的年齡是否大于25:0

看到這里我們會發(fā)現(xiàn)evaluateWithObject:方法返回的是一個BOOL值,如果符合條件就返回YES挖函,不符合就返回NO状植。而即使是最簡單的使用也有一些大用處,比如以前我們寫判斷手機(jī)號碼怨喘、郵編等等浅萧。

例二: 判斷手機(jī)號是否正確
  • (BOOL)checkPhoneNumber:(NSString *)phoneNumber
    {
    NSString *regex = @"^[1][3-8]\d{9}$";
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
    return [pred evaluateWithObject:phoneNumber];
    }

NSString *phoneNumber = @"138974580439";
NSLog(@"電話號碼是否正確:%d", [self checkPhoneNumber:phoneNumber]);

輸出結(jié)果如下:

2016-06-22 21:58:13.623 NSPredicate[1092:61061] 電話號碼是否正確:0


更多正則表達(dá)式請參考[iOS正則表達(dá)式的簡單使用](http://www.reibang.com/p/4b2bad4ad3e8)

###2.使用謂詞過濾集合

此部分是我們需要掌握的重點(diǎn),因為從這里我們就可以看到謂詞的真正的強(qiáng)大之處

其實謂詞本身就代表了一個邏輯條件哲思,計算謂詞之后返回的結(jié)果永遠(yuǎn)為BOOL類型的值。而謂詞最常用的功能就是對集合進(jìn)行過濾吩案。當(dāng)程序使用謂詞對集合元素進(jìn)行過濾時棚赔,程序會自動遍歷其元素,并根據(jù)集合元素來計算謂詞的值徘郭,當(dāng)這個集合中的元素計算謂詞并返回YES時靠益,這個元素才會被保留下來。請注意程序會自動遍歷其元素残揉,它會將自動遍歷過之后返回為YES的值重新組合成一個集合返回胧后。

- NSArray提供了如下方法使用謂詞來過濾集合
`- (NSArray *)filteredArrayUsingPredicate:(NSPredicate *)predicate:`使用指定的謂詞過濾NSArray集合,返回符合條件的元素組成的新集合

- NSMutableArray提供了如下方法使用謂詞來過濾集合
`- (void)filterUsingPredicate:(NSPredicate *)predicate:`使用指定的謂詞過濾NSMutableArray抱环,剔除集合中不符合條件的元素

- NSSet提供了如下方法使用謂詞來過濾集合
`- (NSSet *)filteredSetUsingPredicate:(NSPredicate *)predicate NS_AVAILABLE(10_5, 3_0):`作用同NSArray中的方法

- NSMutableSet提供了如下方法使用謂詞來過濾集合
`- (void)filterUsingPredicate:(NSPredicate *)predicate NS_AVAILABLE(10_5, 3_0):`作用同NSMutableArray中的方法壳快。

>通過上面的描述可以看出,使用謂詞過濾不可變集合和可變集合的區(qū)別是:過濾不可變集合時镇草,會返回符合條件的集合元素組成的新集合眶痰;過濾可變集合時,沒有返回值梯啤,會直接剔除不符合條件的集合元素

下面讓我們來看幾個例子:

例一:
NSMutableArray *arrayM = [@[@20, @40, @50, @30, @60, @70] mutableCopy];
//  過濾大于50的值
NSPredicate *pred1 = [NSPredicate predicateWithFormat:@"SELF > 50"];
[arrayM filterUsingPredicate:pred1];
NSLog(@"arrayM:%@", arrayM);
NSArray *array = @[[ZLPersonModel personWithName:@"Jack" age:20 sex:ZLPersonSexMale],
                  [ZLPersonModel personWithName:@"Rose" age:22 sex:ZLPersonSexFamale],
                  [ZLPersonModel personWithName:@"Jackson" age:30 sex:ZLPersonSexMale],
                  [ZLPersonModel personWithName:@"Johnson" age:35 sex:ZLPersonSexMale]];
//  要求取出包含‘son’的元素
NSPredicate *pred2 = [NSPredicate predicateWithFormat:@"name CONTAINS 'son'"];
NSArray *newArray = [array filteredArrayUsingPredicate:pred2];
NSLog(@"%@", newArray);
輸出為

PredicteDemo[13660:293822] arrayM:(
60,
70
)
PredicteDemo[13660:293822] (
"[name = Jackson, age = 30, sex = 0]",
"[name = Johnson, age = 35, sex = 0]"
)

從這個例子我們就可以看到NSPredicate可以很快的從數(shù)組中選出符合條件的對象竖伯。

###3.在謂詞中使用占位符參數(shù)

我們上面所有的例子中謂詞總是固定的,然而我們在現(xiàn)實中處理變量時決定了謂詞應(yīng)該是可變的。下面我們來看看如果讓謂詞變化起來七婴。

首先如果我們想在謂詞表達(dá)式中使用變量祟偷,那么我們需要了解下列兩種占位符:

` %K`:用于動態(tài)傳入屬性名

`%@`:用于動態(tài)設(shè)置屬性值

其實相當(dāng)于變量名與變量值,除此之外打厘,還可以在謂詞表達(dá)式中使用動態(tài)改變的屬性值修肠,就像環(huán)境變量一樣

`NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF CONTAINS $VALUE"];`

上述表達(dá)式中,`$VALUE`是一個可以動態(tài)變化的值婚惫,它其實最后是在字典中的一個key氛赐,所以可以根據(jù)你的需要寫不同的值,但是必須有$開頭先舷,隨著程序改變`$VALUE`這個謂詞表達(dá)式的比較條件就可以動態(tài)改變艰管。

下面我們通過一個例子來看看這三個重要的占位符應(yīng)該如何使用

例一:

NSArray *array = @[[PersonModel personWithName:@"Jack" age:20 sex:PersonSexMale],
[PersonModel personWithName:@"Rose" age:22 sex:PersonSexFamale],
[PersonModel personWithName:@"Jackson" age:30 sex:PersonSexMale],
[PersonModel personWithName:@"Johnson" age:35 sex:PersonSexMale]];
// 定義一個property來存放屬性名,定義一個value來存放值
NSString *property = @"name";
NSString *value = @"Jack";
// 該謂詞的作用是如果元素中property屬性含有值value時就取出放入新的數(shù)組內(nèi)蒋川,這里是name包含Jack
NSPredicate *pred = [NSPredicate predicateWithFormat:@"%K CONTAINS %@", property, value];
NSArray *newArray = [array filteredArrayUsingPredicate:pred];
NSLog(@"newArray:%@", newArray);

// 創(chuàng)建謂詞牲芋,屬性名改為age,要求這個age包含$VALUE字符串
NSPredicate *predTemp = [NSPredicate predicateWithFormat:@"%K > $VALUE", @"age"];
// 指定$VALUE的值為 25
NSPredicate *pred1 = [predTemp predicateWithSubstitutionVariables:@{@"VALUE" : @25}];
NSArray *newArray1 = [array filteredArrayUsingPredicate:pred1];
NSLog(@"newArray1:%@", newArray1);

// 修改 $VALUE的值為32
NSPredicate *pred2 = [predTemp predicateWithSubstitutionVariables:@{@"VALUE" : @32}];
NSArray *newArray2 = [array filteredArrayUsingPredicate:pred2];
NSLog(@"newArray2:%@", newArray2);

輸出為

PredicteDemo[14542:309494] newArray:(
"[name = Jack, age = 20, sex = 0]",
"[name = Jackson, age = 30, sex = 0]"
)
PredicteDemo[14542:309494] newArray1:(
"[name = Jackson, age = 30, sex = 0]",
"[name = Johnson, age = 35, sex = 0]"
)
PredicteDemo[14542:309494] newArray2:(
"[name = Johnson, age = 35, sex = 0]"
)

從上例中我們主要可以看出來%K和$VALUE的含義捺球。


`??本文借鑒了很多前輩的文章缸浦,如果有不對的地方請指正,歡迎大家一起交流學(xué)習(xí)   xx_cc.`
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末氮兵,一起剝皮案震驚了整個濱河市裂逐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌泣栈,老刑警劉巖卜高,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異南片,居然都是意外死亡掺涛,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進(jìn)店門疼进,熙熙樓的掌柜王于貴愁眉苦臉地迎上來薪缆,“玉大人,你說我怎么就攤上這事伞广〖鹈保” “怎么了?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵嚼锄,是天一觀的道長诞外。 經(jīng)常有香客問我,道長灾票,這世上最難降的妖魔是什么峡谊? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上既们,老公的妹妹穿的比我還像新娘濒析。我一直安慰自己,他們只是感情好啥纸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布号杏。 她就那樣靜靜地躺著,像睡著了一般斯棒。 火紅的嫁衣襯著肌膚如雪盾致。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天荣暮,我揣著相機(jī)與錄音庭惜,去河邊找鬼。 笑死穗酥,一個胖子當(dāng)著我的面吹牛护赊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播砾跃,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼骏啰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了抽高?” 一聲冷哼從身側(cè)響起判耕,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎翘骂,沒想到半個月后壁熄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡雏胃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了志鞍。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瞭亮。...
    茶點(diǎn)故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖固棚,靈堂內(nèi)的尸體忽然破棺而出统翩,到底是詐尸還是另有隱情,我是刑警寧澤此洲,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布厂汗,位于F島的核電站,受9級特大地震影響呜师,放射性物質(zhì)發(fā)生泄漏娶桦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望衷畦。 院中可真熱鬧栗涂,春花似錦、人聲如沸祈争。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽菩混。三九已至忿墅,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間沮峡,已是汗流浹背疚脐。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留帖烘,地道東北人亮曹。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像秘症,于是被迫代替她去往敵國和親照卦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評論 2 354

推薦閱讀更多精彩內(nèi)容