iOS本地搜索之NSExpression

作者: 船长_ | 来源:发表于2016-06-11 11:33 被阅读922次

    1.场景需求

    • 服务器返回一个数组,数组里面包含若干条数据,字典转模型后,一个新的数组,里面若干条模型对象;通过searchBar或者textField要求可以本地筛选,比如每个模型对象包含price,job,userName,company,要求输入这些关键字能实现本地筛选;

    2.分析

    • 利用NSExpression,对本地模型数组进行遍历,对用户输入的关键字进行逐个匹配(price/job/userName/company);如果找到相符合的,就把新的数组作为数据源返回,并刷新cell;

    关键方法

    + (NSPredicate *)predicateWithLeftExpression:(NSExpression *)lhs
                                 rightExpression:(NSExpression *)rhs
                                        modifier:(NSComparisonPredicateModifier)modifier
                                            type:(NSPredicateOperatorType)type
                                         options:(NSUInteger)options
    

    解析参数

    lhs:左边的表达式。
    rhs:右边的表达式。
    modifier:应用的修改符。(ANY或者ALL)
    type:谓词运算符类型。
    options:要应用的选项。没有选项的话则为0。
    

    NSComparisonPredicate选项

    • NSCaseInsensitivePredicateOption:不区分大小写的谓词。你通过在谓词格式字符串中加入后面带有[c]的字符串操作(比如,"NeXT" like[c] "next")来表达这一选项。
    • NSDiacriticInsensitivePredicateOption:忽视发音符号的谓词。你通过在谓词格式字符串中加入后面带有[d]的字符串操作(比如,"naïve" like[d] "naive")来表达这一选项。
    • NSNormalizedPredicateOption:表示待比较的字符串已经被预处理了。这一选项取代了NSCaseInsensitivePredicateOption和NSDiacriticInsensitivePredicateOption,旨在用作性能优化的选项。你可以通过在谓词格式字符串中加入后面带有[n]的字符串(比如,"WXYZlan" matches[n] ".lan")来表达这一选项。
    • NSLocaleSensitivePredicateOption:表明要使用<,<=,=,=>,> 作为比较的字符串应该使用区域识别的方式处理。你可以通过在<,<=,=,=>,>其中之一的操作符后加入[l](比如,"straße" >[l] "strasse")以便在谓词格式字符串表达这一选项。

    3.核心代码,封装成一个方法方便多个地方调用

    -(NSArray*)filterWithString:(NSString*)text{
        if(!text||text.length<=0)
        {
            return self.arrayBak;
        }
        NSString *searchText =   text;//searchController.searchBar.text;
        NSMutableArray *searchResults = [self.arrayBak mutableCopy];
    
        // strip out all the leading and trailing spaces
        NSString *strippedString = [searchText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    
        // break up the search terms (separated by spaces)
        NSArray *searchItems = nil;
        if (strippedString.length > 0) {
            searchItems = [strippedString componentsSeparatedByString:@" "];
        }
    
       // build all the "AND" expressions for each value in the searchString
        NSMutableArray *andMatchPredicates = [NSMutableArray array];
        
        for (NSString *searchString in searchItems) {
    
         NSMutableArray *searchItemsPredicate = [NSMutableArray array];
    
            NSExpression*lhs;
            NSExpression*rhs;
            NSPredicate*finalPredicate;
            {
                lhs = [NSExpression expressionForKeyPath:@"userName"];//名字
                rhs = [NSExpression expressionForConstantValue:searchString];
                finalPredicate = [NSComparisonPredicate
                                           predicateWithLeftExpression:lhs
                                           rightExpression:rhs
                                           modifier:NSDirectPredicateModifier
                                           type:NSContainsPredicateOperatorType
                                           options:NSCaseInsensitivePredicateOption];
            [searchItemsPredicate addObject:finalPredicate];
            }
    
           {
                lhs = [NSExpression expressionForKeyPath:@"job"];//职位
                rhs = [NSExpression expressionForConstantValue:searchString];
                finalPredicate = [NSComparisonPredicate
                                  predicateWithLeftExpression:lhs
                                  rightExpression:rhs
                                  modifier:NSDirectPredicateModifier
                                  type:NSContainsPredicateOperatorType
                                  options:NSCaseInsensitivePredicateOption];
                [searchItemsPredicate addObject:finalPredicate];
            }
    
           {
                lhs = [NSExpression expressionForKeyPath:@"upCompany"];//职位
                rhs = [NSExpression expressionForConstantValue:searchString];
                finalPredicate = [NSComparisonPredicate
                                  predicateWithLeftExpression:lhs
                                  rightExpression:rhs
                                  modifier:NSDirectPredicateModifier
                                  type:NSContainsPredicateOperatorType
                                  options:NSCaseInsensitivePredicateOption];
                [searchItemsPredicate addObject:finalPredicate];
            }
    
            NSNumber*targetNumber=@([searchString integerValue]*100);
            if (targetNumber != nil&&targetNumber.integerValue!=0) {   // searchString may not convert to a number
                lhs = [NSExpression expressionForKeyPath:@"price"]; 
                rhs = [NSExpression expressionForConstantValue:targetNumber];
                finalPredicate = [NSComparisonPredicate
                                  predicateWithLeftExpression:lhs
                                  rightExpression:rhs
                                  modifier:NSDirectPredicateModifier
                                  type:NSEqualToPredicateOperatorType
                                  options:NSCaseInsensitivePredicateOption];
                [searchItemsPredicate addObject:finalPredicate];
     }
    
     // at this OR predicate to our master AND predicate
      NSCompoundPredicate *orMatchPredicates = [NSCompoundPredicate orPredicateWithSubpredicates:searchItemsPredicate];
            [andMatchPredicates addObject:orMatchPredicates];
        }
    
     // match up the fields of the Product object
        NSCompoundPredicate *finalCompoundPredicate =
        [NSCompoundPredicate andPredicateWithSubpredicates:andMatchPredicates];
        searchResults = [[searchResults filteredArrayUsingPredicate:finalCompoundPredicate] mutableCopy];
    
        return searchResults;
    }
    

    4.方法的使用

    监听用户的输入的关键字调用封装的方法搜索,拿到搜索得到的数组刷新tableView

    NSArray*searchResults=[self filterWithString:searchController.searchBar.text];
    // hand over the filtered results to our search results table
    FTFSearchResultsViewController   *tableController = (FTFSearchResultsViewController *)self.searchController.searchResultsController;
    tableController.filteredResumeArray = searchResults;
    [tableController.tableView reloadData];
    

    相关文章

      网友评论

      • GCYZWD:苹果官网的代码实例,被你拿来用了。
      • __阳阳:不错不错, 正好用到
      • 酸三角:你好,楼主有demo,你分享的代码 没有注释 小白看不懂啊 求教

      本文标题:iOS本地搜索之NSExpression

      本文链接:https://www.haomeiwen.com/subject/dkasdttx.html