iOS本地搜索之NSExpression

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];

你可能感兴趣的:(iOS本地搜索之NSExpression)