sunshinelww

执着的程序员.

要有最朴素的生活和最遥远的梦想,即使明日天寒地冻、路遥马亡 .


iOS开发之NSPredicate的使用

最近在看一个开源项目,里面用到了NSPredicate类,感觉Foundation提供的NSPredicate类及其过滤表达式特别强大,所以特地去学习了下。话不多说,下面我们来一起学习下吧。

NSPredicate有三个子类,如图是其类结构图

NSPredicate类图.png

NSPredicate主要用生成基本的条件表达式,如:

   NSMutableArray *array=[NSMutableArray array];
    [array addObject:[[Student alloc] initWith:@"lww" age:20]];
    [array addObject:[[Student alloc] initWith:@"wy" age:20]];
    [array addObject:[[Student alloc] initWith:@"LWW" age:21]];
    [array addObject:[[Student alloc] initWith:@"sunshinelww" age:22]];
    NSPredicate *basicPredicate=[NSPredicate predicateWithFormat:@"name = 'lww'"];
   [array filterUsingPredicate: basicPredicate]; //通过条件表达式筛选数组元素

输出结果: 当然NSPredicate还可以生成很多复杂的谓词表达式,在此我们不详细展开。

下面我们来看下NSCompoundPredicate类,这个类主要用于组合谓词表达式,有三种组合方式:AND,OR和NOT

NSMutableArray *predicateArray=[NSMutableArray array];
NSPredicate *basicPredicate1=[NSPredicate predicateWithFormat:@"name = 'lww'"];
NSPredicate *basicPredicate2=[NSPredicate predicateWithFormat:@"age = 20"];[predicateArray addObject: basicPredicate1];
[predicateArray addObject: basicPredicate2];

NSCompoundPredicate *orMatchPredicate=[NSCompoundPredicate orPredicateWithSubpredicates:predicateArray]; ///对数组中的谓词表达式取或
NSCompoundPredicate *andMatchPredicate=[NSCompoundPredicate andPredicateWithSubpredicates:predicateArray];///对数组中的谓词表达式取与
[NSCompoundPredicate notPredicateWithSubpredicate: basicPredicate1]; ///对basicPredicate1取反

通过NSCompoundPredicate我们可以灵活实现多谓词条件相结合的方式进行过滤。

最后我们看下NSComparisonPredicate类的使用,NSComparisonPredicate主要用来比较两个表达式的结果,其中创建NSComparisonPredicate对象需要指定左表达式、右表达式和运算符。构造方法如下:

- (instancetype)initWithLeftExpression:(NSExpression *)lhs 
                       rightExpression:(NSExpression *)rhs 
                              modifier:(NSComparisonPredicateModifier)modifier 
                                  type:(NSPredicateOperatorType)type 
                               options:(NSComparisonPredicateOptions)options;

表达式类为NSExpression,NSExpression分为constant Value和key path等。 其次是操作符枚举NSPredicateOperatorType,主要有:

typedef NS_ENUM(NSUInteger, NSPredicateOperatorType) {
    NSLessThanPredicateOperatorType = 0, // compare: returns NSOrderedAscending
    NSLessThanOrEqualToPredicateOperatorType, // compare: returns NSOrderedAscending || NSOrderedSame
    NSGreaterThanPredicateOperatorType, // compare: returns NSOrderedDescending
    NSGreaterThanOrEqualToPredicateOperatorType, // compare: returns NSOrderedDescending || NSOrderedSame
    NSEqualToPredicateOperatorType, // isEqual: returns true
    NSNotEqualToPredicateOperatorType, // isEqual: returns false
    NSMatchesPredicateOperatorType,
    NSLikePredicateOperatorType,
    NSBeginsWithPredicateOperatorType,
    NSEndsWithPredicateOperatorType,
    NSInPredicateOperatorType, // rhs contains lhs returns true
    NSCustomSelectorPredicateOperatorType,
    NSContainsPredicateOperatorType NS_ENUM_AVAILABLE(10_5, 3_0) = 99, // lhs contains rhs returns true
    NSBetweenPredicateOperatorType NS_ENUM_AVAILABLE(10_5, 3_0)
};

通过指定操作符我们可以对两个表达式进行比较。 该函数最后一个参数是枚举NSComparisonPredicateOptions用来指定比较选项,定义如下:

typedef NS_OPTIONS(NSUInteger, NSComparisonPredicateOptions) {
    NSCaseInsensitivePredicateOption = 0x01, //大小写不敏感
    NSDiacriticInsensitivePredicateOption = 0x02, //忽视发音符号
    NSNormalizedPredicateOption NS_ENUM_AVAILABLE(10_6, 4_0) = 0x04, /* 表示待比较的字符串已经被预处理了。这一选项取代了NSCaseInsensitivePredicateOption和NSDiacriticInsensitivePredicateOption,旨在用作性能优化的选项 */
};

最后用一个例子综合应用上述三个类。代码如下:

    NSMutableArray *array=[NSMutableArray array];
    [array addObject:[[Student alloc] initWith:@"lww" age:20]];
    [array addObject:[[Student alloc] initWith:@"wy" age:20]];
    [array addObject:[[Student alloc] initWith:@"LWW" age:21]];
    [array addObject:[[Student alloc] initWith:@"sunshinelww" age:22]];

    
    NSExpression *lhs=[NSExpression expressionForKeyPath:@"name"];
    NSExpression *rhs=[NSExpression expressionForConstantValue:@"lww"];
    
    NSPredicate *predicate1=[NSComparisonPredicate predicateWithLeftExpression:lhs rightExpression:rhs modifier:NSDirectPredicateModifier type:NSContainsPredicateOperatorType options:0]; //name字符串包含“lww”
    
    lhs=[NSExpression expressionForKeyPath:@"age"];
    rhs=[NSExpression expressionForConstantValue:@20];

    NSPredicate *predicate2=[NSComparisonPredicate predicateWithLeftExpression:lhs rightExpression:rhs modifier:NSDirectPredicateModifier type:NSEqualToPredicateOperatorType options:NSCaseInsensitivePredicateOption]; //age=20

    NSMutableArray *predicateArray=[NSMutableArray array];
    [predicateArray addObject:predicate1];
    [predicateArray addObject:predicate2];
    
    NSCompoundPredicate *andMatchPredicate=[NSCompoundPredicate andPredicateWithSubpredicates:predicateArray]; //对两个谓词求与

    [array filterUsingPredicate:andMatchPredicate];
   
    for (Student *stu in array) {
        [stu printAddress];
    }

输出结果

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦