NSPredicate 的使用

NSPredicate 这个类主要有两个方面的作用:

  1. 从集合类中过滤数据
  2. 和正则表达式进行正则判断(比方说验证手机号,邮箱,IP地址是否满足要求,其实还是过滤数据)

集合中过滤数据

@interface Person : NSObject
@property NSString *firstName;
@property NSString *lastName;
@property NSNumber *age;
@end

@implementation Person

- (NSString *)description {
    return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}

@end

#pragma mark -

NSArray *firstNames = @[ @"Alice", @"Bob", @"Charlie", @"Quentin" ];
NSArray *lastNames = @[ @"Smith", @"Jones", @"Smith", @"Alberts" ];
NSArray *ages = @[ @24, @27, @33, @31 ];

NSMutableArray *people = [NSMutableArray array];
[firstNames enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    Person *person = [[Person alloc] init];
    person.firstName = firstNames[idx];
    person.lastName = lastNames[idx];
    person.age = ages[idx];
    [people addObject:person];
}]; 
  1. 过滤对象的firstName属性 firstName = 'Bob',执行结果是获取 firstName = 'Bob' 的数组
NSPredicate *bobPredicate = [NSPredicate predicateWithFormat:@"firstName = 'Bob'"];
NSLog(@"Bobs: %@", [people filteredArrayUsingPredicate:bobPredicate]);
["Bob Jones"]
  1. 过滤对象 age >= 30
NSPredicate *thirtiesPredicate = [NSPredicate predicateWithFormat:@"age >= 30"];
NSLog(@"30's: %@", [people filteredArrayUsingPredicate:thirtiesPredicate]);
["Charlie Smith", "Quentin Alberts"]
  1. 过滤年龄 在 26和30之间的情况
 NSPredicate *agePredicate2 = [NSPredicate predicateWithFormat:@"age BETWEEN {26, 30}"];
 NSLog(@"age2:%@",[people filteredArrayUsingPredicate:agePredicate2]);
    
  1. 过滤年龄在 26 到30 之间,firstName为 'Alice','Bob' 的情况
 NSPredicate *agePredicate4 = [NSPredicate predicateWithFormat:@"SELF.firstName IN {'Alice','Bob'} && SELF.age BETWEEN {26,30} "];
  NSLog(@"age4:%@",[people filteredArrayUsingPredicate:agePredicate4]);

5.过滤firstName 为alice(忽略大小写和重低音的情况)

 NSPredicate *agePredicate5 = [NSPredicate predicateWithFormat:@"firstName LIKE[cd] 'alice'"];
 NSLog(@"agePredicate5:%@",[people filteredArrayUsingPredicate:agePredicate5]);

一些谓词

基本比较

=, ==:左边的表达式和右边的表达式相等。(谓词中 = 和 == 一样的,都是比较,没有赋值的意思)
=, =>:左边的表达式大于或者等于右边的表达式。
<=, =<:左边的表达式小于等于右边的表达式。

:左边的表达式大于右边的表达式。
<:左边的表达式小于右边的表达式。
!=, <>:左边的表达式不等于右边的表达式。
BETWEEN:左边的表达式等于右边的表达式的值或者介于它们之间。右边是一个有两个指定上限和下限的数值的数列(指定顺序的数列)。比如,1 BETWEEN { 0 , 33 },或者INPUT BETWEEN {LOWER, $UPPER }。

基本符合谓词

  • AND, &&:逻辑与.
  • OR, ||:逻辑或.
  • NOT, !:逻辑非.

字符串比较

字符串比较在默认的情况下是区分大小写和音调的。你可以在方括号中用关键字符c和d来修改操作符以相应的指定不区分大小写和变音符号,比如firstname BEGINSWITH[cd] $FIRST_NAME。

BEGINSWITH:左边的表达式以右边的表达式作为开始。
CONTAINS:左边的表达式包含右边的表达式。
ENDSWITH:左边的表达式以右边的表达式作为结束。
LIKE:左边的表达式等于右边的表达式:?和可作为通配符,其中?匹配1个字符,匹配0个或者多个字符。
MATCHES:左边的表达式根据ICU v3(更多内容请查看ICU User Guide for Regular Expressions)的regex风格比较,等于右边的表达式。

合计操作

关系操作

ANY,SOME:指定下列表达式中的任意元素。比如,ANY children.age < 18。(特别要注意的是操作对象必须是集合,比方说数组套数组的情况,操作对象就是数组) 集合中任意一个元素满足条件,就返回YES

ALL:指定下列表达式中的所有元素。比如,ALL children.age < 18。 集合中所有元素都满足条件,才返回YES

NONE:指定下列表达式中没有的元素。比如,NONE children.age < 18。它在逻辑上等于NOT (ANY ...)。 集合中没有任何元素满足条件就返回YES。

IN:等于SQL的IN操作,左边的表达必须出现在右边指定的集合中。比如,name IN { 'Ben', 'Melissa', 'Nick' } 等价于SQL语句中的IN运算符,只有当左边表达式或值出现在右边的集合中才会返回YES

数组操作

array[index]:指定数组中特定索引处的元素。
array[FIRST]:指定数组中的第一个元素。
array[LAST]:指定数组中的最后一个元素。
array[SIZE]:指定数组的大小。

布尔值谓词

TRUEPREDICATE:结果始终为真的谓词。
FALSEPREDICATE:结果始终为假的谓词。

直接量

在谓词表达式中可以使用如下直接量

FALSE、NO:代表逻辑假
TRUE、YES:代表逻辑真
NULL、NIL:代表空值
SELF:代表正在被判断的对象自身
"string"或'string':代表字符串
数组:和c中的写法相同,如:{'one', 'two', 'three'}。
数值:包括证书、小数和科学计数法表示的形式
十六进制数:0x开头的数字
八进制:0o开头的数字
二进制:0b开头的数字
3.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
注:虽然大小写都可以,但是更推荐使用大写来表示这些保留字

SELF 指的就是要被判断的谓词对象。

过滤方面的具体使用

例子1:获取选中的规格ID

isSelected

- (NSString *)SpecValIds {
   // 创建谓词对象
    NSPredicate* predicate = [NSPredicate predicateWithFormat:@"isSelected == %d",YES];
   //self.platProductAttributeAndSpecificationDto.ProductSpecificationDtos 为一个数组
    NSMutableArray *tmparr = [self.platProductAttributeAndSpecificationDto.ProductSpecificationDtos filteredArrayUsingPredicate:predicate];
    // 从数组中拿到对象,对这个对象的id进行去重,并且把 id 放到一个数组中进行返回
    NSArray *editReturnedModeltmparr = [tmparr valueForKeyPath:@"@distinctUnionOfObjects.id"];//
   //  NSString iOS 将数组中的元素用符号拼接字符串的方法
    NSString *string = [editReturnedModeltmparr componentsJoinedByString:@","];
    return string;
}

例子2:数据的过滤,城市搜索

一般的城市搜索,都是支持字母拼写和汉字搜索的。
可以使用谓词,也可以不使用谓词。

方式一,不使用谓词

+ (NSArray *)searchcityModelsWithSeatchText:(NSString *)searchText{
    NSMutableArray *array = [NSMutableArray array];
    //拼音转化为大写
    searchText = [searchText uppercaseString];
    for (DKCityModel *obj in _cityModels) {
        if ([obj.name.uppercaseString containsString:searchText] || [obj.pinYin.uppercaseString containsString:searchText] || [obj.pinYinHead.uppercaseString containsString:searchText]) {
            [array addObject:obj];
        }
    }
    return array;
}

方式二 :使用谓词

searchText  = searchText.uppercaseString;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@" pinYinHead.uppercaseString  contains %@ or  name.uppercaseString  contains %@  or pinYin.uppercaseString  contains %@ ",searchText,searchText,searchText];
 return [_cityModels filteredArrayUsingPredicate:predicate];

很明显使用谓词代码量更少,代码更简单。

正则表达式进行判断

利用NSPredicate 的evaluateWithObject 方法进行正则匹配。

#pragma 正则匹配手机号
+ (BOOL)checkTelNumber:(NSString *) telNumber {
    NSString *pattern = @^1+[3578]+\d{9};
    NSPredicate *pred = [NSPredicate predicateWithFormat:@SELF MATCHES %@, pattern];
    BOOL isMatch = [pred evaluateWithObject:telNumber];
    return isMatch;
}
  
  
#pragma 正则匹配用户密码6-18位数字和字母组合
+ (BOOL)checkPassword:(NSString *) password {
    NSString *pattern = @^(?![0-9]+$)(?![a-zA-Z]+$)[a-zA-Z0-9]{6,18};
    NSPredicate *pred = [NSPredicate predicateWithFormat:@SELF MATCHES %@, pattern];
    BOOL isMatch = [pred evaluateWithObject:password];
    return isMatch;
      
}
  
#pragma 正则匹配用户姓名,20位的中文或英文
+ (BOOL)checkUserName : (NSString *) userName {
    NSString *pattern = @^[a-zA-Z一-龥]{1,20};
    NSPredicate *pred = [NSPredicate predicateWithFormat:@SELF MATCHES %@, pattern];
    BOOL isMatch = [pred evaluateWithObject:userName];
    return isMatch;  
}
  
  
#pragma 正则匹配用户身份证号15或18位
+ (BOOL)checkUserIdCard: (NSString *) idCard{
    NSString *pattern = @(^[0-9]{15}$)|([0-9]{17}([0-9]|X)$);
    NSPredicate *pred = [NSPredicate predicateWithFormat:@SELF MATCHES %@, pattern];
    BOOL isMatch = [pred evaluateWithObject:idCard];
    return isMatch;
}
  
#pragma 正则匹员工号,12位的数字
+ (BOOL)checkEmployeeNumber : (NSString *) number{
    NSString *pattern = @^[0-9]{12}; 
    NSPredicate *pred = [NSPredicate predicateWithFormat:@SELF MATCHES %@, pattern];
    BOOL isMatch = [pred evaluateWithObject:number];
    return isMatch;
      
}
  
#pragma 正则匹配URL
+ (BOOL)checkURL : (NSString *) url{
    NSString *pattern = @^[0-9A-Za-z]{1,50};
    NSPredicate *pred = [NSPredicate predicateWithFormat:@SELF MATCHES %@, pattern];
    BOOL isMatch = [pred evaluateWithObject:url];
    return isMatch;
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354

推荐阅读更多精彩内容