zoukankan      html  css  js  c++  java
  • iOS开发-NSPredicate

    Cocoa中谓词(Predicate)提供了一个通用的查询方式处理数据,可以获取和指定数据的过滤形式,Cocoa实际开发中可以是使用NSPredicate及其父类NSComparisonPredicate和NSCompoundPredicate.其风格类似于SQL查询语言和正则表达式的混合体,提供了具有表现力的,自然语言界面来定义一个集合被搜寻的逻辑条件。一般来说稍微操作过数据库基本上很容易理解其中的方法,至于使用的方法也很简单。

    集合中的NSPredicate

    Foundation提供使用谓词(predicate)来过滤NSArray/NSMutableArray&NSSet/NSMutableSet的方法。
    不可变的集合,NSArray&NSSet,可以通过评估接收到的predicate来返回一个不可变集合的方法filteredArrayUsingPredicate和filteredSetUsingPredicate;
    可变集合,NSMutableArray&NSMutableSet,可以使用方法filterUsingPredicate:可以通过运行接收到的谓词来移除评估结果为FALSE的对象。

    首先来一段比较简单的代码: 

        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF IN %@", @[@"keso", @"FlyElephant", @"博客园"]];
        if ([predicate evaluateWithObject:@"keso"]) {
            NSLog(@"keso");
        };
    

     第一行代码初始化一个查询条件,第二句就是判断数据在不在结果集中,跟SQL基本上一样,通过IN就能大概了解其功能,SELF表示本身,非常常用。

    接下来可以类似于SQL中like语句的代码:

       NSArray *array = [[NSArray alloc]initWithObjects:@"北京",@"上海",@"广州",@"深圳",nil];
        NSPredicate *preBegin= [NSPredicate predicateWithFormat:@"SELF beginswith[c] %@",@"北"];
        NSPredicate *preContain= [NSPredicate predicateWithFormat:@"SELF contains[c] %@",@"海"];
        
        NSLog(@"%@",[array filteredArrayUsingPredicate:preBegin][0]);
        NSLog(@"%@",[array filteredArrayUsingPredicate:preContain][0]);
    

     第一次就是先初始化数组,然后创建条件,通过filteredArrayUsingPredicate过滤数组;

    NSDictionary可以用谓词来过滤它的键和值(两者都为NSArray对象);

    NSOrderedSet可以由过滤的NSArray或NSSet生成一个新的有序的集,或者NSMutableSet可以简单的removeObjectsInArray来传递通过否定predicate过滤的对象。

    Core Data中的NSPredicate

    谓词的在Core Data同样适用,在管理对象环境中,谓词由持久化存储助理(persistent store coordinator)评估,而集合则是内存中过滤。这时候我们有必要里了解一下基本比较运算符:

    • =, ==:左边的表达式和右边的表达式相等。
    • >=, =>:左边的表达式大于或者等于右边的表达式。
    • <=, =<:左边的表达式小于等于右边的表达式。
    • >:左边的表达式大于右边的表达式。
    • <:左边的表达式小于右边的表达式。
    • !=, <>:左边的表达式不等于右边的表达式。
    BETWEEN:左边的表达式等于右边的表达式的值或者介于它们之间。右边是一个有两个指定上限和下限的数值的数列(指定顺序的数列)。比如,1 BETWEEN { 0 , 33 },或者$INPUT BETWEEN { $LOWER, $UPPER }。可参考以下代码:
     NSPredicate *betweenPredicate =
        [NSPredicate predicateWithFormat: @"attributeName BETWEEN %@", @[@1, @10]];
        
        NSDictionary *dictionary = @{ @"attributeName" : @5 };
        
        BOOL between = [betweenPredicate evaluateWithObject:dictionary];
        if (between) {
            NSLog(@"比较运算符between");
        } 
    基本复合谓词
    • AND, &&:逻辑与.
    • OR, ||:逻辑或.
    • NOT, !:逻辑非
    字符串比较
    字符串比较非常常用,以下的都应该比较熟悉:
    • BEGINSWITH[cd] $FIRST_NAME。
    • BEGINSWITH:左边的表达式以右边的表达式作为开始。
    • CONTAINS:左边的表达式包含右边的表达式。
    • ENDSWITH:左边的表达式以右边的表达式作为结束。
    • LIKE:左边的表达式等于右边的表达式:?和*可作为通配符,其中?匹配1个字符,*匹配0个或者多个字符。
    • MATCHES:左边的表达式根据ICU v3的regex风格比较,等于右边的表达式。
    可参考以下代码:
        NSString *regex = @"[A-Za-z]+";
        NSPredicate *matchpredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
        
        if ([matchpredicate evaluateWithObject:@"keso"]) {
            NSLog(@"匹配成功");
        }
    关系操作
    • ANY,SOME:指定下列表达式中的任意元素。比如,ANY children.age < 18。
    • ALL:指定下列表达式中的所有元素。比如,ALL children.age < 18。
    • NONE:指定下列表达式中没有的元素。比如,NONE children.age < 18。它在逻辑上等于NOT (ANY ...)。
    • IN:等于SQL的IN操作,左边的表达必须出现在右边指定的集合中。比如,name IN { 'Ben', 'Melissa', 'Nick' }。
    数组操作
    • array[index]:指定数组中特定索引处的元素。
    • array[FIRST]:指定数组中的第一个元素。
    • array[LAST]:指定数组中的最后一个元素。
    • array[SIZE]:指定数组的大小。
    布尔值谓词
    • TRUEPREDICATE:结果始终为真的谓词。
    • FALSEPREDICATE:结果始终为假的谓词。
    下面提供一个简单使用谓词搜索类对象的代码:
    新建一个People类,头文件:
    @interface People : NSObject
    
    @property (strong,nonatomic) NSString *FirstName;
    
    @property (strong,nonatomic) NSString *LastName;
    
    @property (nonatomic) NSInteger Height;
    
    - (NSString *)description;
    
    @end
    

     People.m文件:

    @implementation People
    
    - (NSString *)description {
     
       return  [NSString stringWithFormat:@"%@%@",self.LastName, self.FirstName];
    };
    @end
    

     具体实现代码:

        
        NSArray *firstNames =[[NSArray alloc]initWithObjects:@"泽东", @"恩来", @"介石", @"中山", nil];
    
        NSArray *lastNames = @[ @"毛", @"周", @"蒋", @"孙" ];
        NSArray *familiar = @[ @100, @99, @99, @98 ];
        
        NSMutableArray *dataList= [NSMutableArray array];
        [firstNames enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
            People *people= [[People alloc] init];
            people.FirstName = firstNames[idx];
            people.LastName = lastNames[idx];
            
            people.Height= [familiar[idx] integerValue];
            [dataList addObject:people];
        }];
        
        NSPredicate *firstPredicate = [NSPredicate predicateWithFormat:@"FirstName = '恩来'"];
        NSPredicate *lastPredicate = [NSPredicate predicateWithFormat:@"LastName = %@", @"蒋"];
        NSPredicate *heightPredicate = [NSPredicate predicateWithFormat:@"Height < 99"];
      
        //名搜索
        NSLog(@"名: %@",[dataList filteredArrayUsingPredicate:firstPredicate][0]);
    
        
        //姓搜索
        NSLog(@"姓: %@", [dataList filteredArrayUsingPredicate:lastPredicate][0]);
        
        //知名度
        NSLog(@"知名度: %@", [dataList filteredArrayUsingPredicate:heightPredicate][0]);
    

    其实开始讲的NSCompoundPredicate和NSComparisonPredicate,因为有关系操作,基本上类似,如果通过混合搜索可以使用and,or实现,比如一下代码是等价的:

       NSCompoundPredicate *comPredicate=[NSCompoundPredicate andPredicateWithSubpredicates:@[[NSPredicate predicateWithFormat:@"Height > 90"], [NSPredicate predicateWithFormat:@"FirstName = %@", @"介石"]]];
        
       NSPredicate *secondPredicate=[NSPredicate predicateWithFormat:@"(Height > 90) AND (FirstName = %@)", @"介石"];
    

      NSComparisonPredicate有两个调用的静态方法:

    + (NSComparisonPredicate *)predicateWithLeftExpression:(NSExpression *)lhs rightExpression:(NSExpression *)rhs modifier:(NSComparisonPredicateModifier)modifier type:(NSPredicateOperatorType)type options:(NSComparisonPredicateOptions)options;
    + (NSComparisonPredicate *)predicateWithLeftExpression:(NSExpression *)lhs rightExpression:(NSExpression *)rhs customSelector:(SEL)selector;
    

      其实就是一个表达式的拼接的过程,不过具体的实现苹果给封装好了,一下是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)
    };
    

    参考资料:https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html#//apple_ref/doc/uid/TP40001795-SW1

  • 相关阅读:
    数据库导出_导入
    vc6如何调试带参数的main函数
    配置mes
    vc调试大全
    C#中out和ref之间的区别
    TSQL 控制流语句
    删除文件夹及文件夹内的文件
    数据库 存储 研究方向 关键词
    apache 监听多端口
    js 产生随机数
  • 原文地址:https://www.cnblogs.com/xiaofeixiang/p/4264869.html
Copyright © 2011-2022 走看看