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