NSPredicate 这个类主要有两个方面的作用:
- 从集合类中过滤数据
- 和正则表达式进行正则判断(比方说验证手机号,邮箱,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];
}];
- 过滤对象的firstName属性 firstName = 'Bob',执行结果是获取 firstName = 'Bob' 的数组
NSPredicate *bobPredicate = [NSPredicate predicateWithFormat:@"firstName = 'Bob'"];
NSLog(@"Bobs: %@", [people filteredArrayUsingPredicate:bobPredicate]);
["Bob Jones"]
- 过滤对象 age >= 30
NSPredicate *thirtiesPredicate = [NSPredicate predicateWithFormat:@"age >= 30"];
NSLog(@"30's: %@", [people filteredArrayUsingPredicate:thirtiesPredicate]);
["Charlie Smith", "Quentin Alberts"]
- 过滤年龄 在 26和30之间的情况
NSPredicate *agePredicate2 = [NSPredicate predicateWithFormat:@"age BETWEEN {26, 30}"];
NSLog(@"age2:%@",[people filteredArrayUsingPredicate:agePredicate2]);
- 过滤年龄在 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 },或者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;
}