iOS-个人整理20 - UISearchController搜索框与NSPredicate谓词

一、UISearchController

搜索框的用处很大,就不用废话了,在iOS8以前是用UISearchBar加代理实现的。
现在已经废弃,鼓励使用新的UISearchController
首先遵守UISearchResultsUpdating协议

@interface RootTableViewController ()<UISearchResultsUpdating>  

//搜索代理方法,搜索框获得第一响应或内容变化时触发  
-(void)updateSearchResultsForSearchController:(UISearchController *)searchController  
{  
   NSLog(@激活了搜索框");  
}  

再创建UISearchController,因为很多方法都要对搜索框进行判断,写成一个属性

@property (nonatomic,retain)UISearchController *searchC;  

//初始化UISearchController,把搜索框添加在tableView的headerView上
//添加搜索栏  
_searchC = [[UISearchController alloc]initWithSearchResultsController:nil];  
//设置frame  
_searchC.searchBar.frame = CGRectMake(0, 0, 414, 50);  
  
//更新代理  
_searchC.searchResultsUpdater = self;  
  
//搜索结果不变灰  
_searchC.dimsBackgroundDuringPresentation = NO;  
  
//添加到header  
self.tableView.tableHeaderView = _searchC.searchBar;  

这样运行就能看到搜索框了,点击也会打印文字。

二、NSPredicate谓词

光有搜索框没什么卵用,还要有搜索功能,内部的功能就需要谓词来实现了
谓词的功能很强大,同时它还可以使用正则表达式,可以实现各种邮箱验证,手机号验证,以及各种查找功能。
使用的方法

1.创建谓词
NSPredicate *testPredicate = [NSPredicate predicateWithFormat:@"age < 50"];  

谓词的语法也很全面:
Format后面可以跟很多:
(1)比较运算符>,<,==,>=,<=,!=可用于数值及字符串例:@"number > 100"
(2)范围运算符:IN、BETWEEN例:@"number BETWEEN {1,5}" @"address IN {'shanghai','beijing'}"
(3)字符串本身:SELF 例:@“SELF == ‘APPLE’"
(4)字符串相关:

BEGINSWITH、ENDSWITH、CONTAINS例:@"name CONTAIN[cd] 'ang'" //包含某个字符串
@"name BEGINSWITH[c] 'sh'" //以某个字符串开头
@"name ENDSWITH[d] 'ang'" //以某个字符串结束
注:[c]不区分大小写[d]不区分发音符号即没有重音符号[cd]既不区分大小写,也不区分发音符号。

(5)通配符:LIKE例:@"name LIKE[cd] 'er'" //代表通配符,Like也接受[cd]. @"name LIKE[cd] '???er'"

(6)正则表达式:MATCHES例:NSString *regex = @"^A.+e$"; //以A开头,e结尾 @"name MATCHES %@",regex
用正则表达式简单匹配一个邮箱

    /* 
   正则表达式常用的  
    ^ ---  匹配输入字符串的开始位置 
    $ ---  匹配输入字符串的结束位置 
    * --- 匹配前面的子表达式任意次 
     + --- 匹配前面的子表达式一次或多次 
     ? --- 匹配前面的子表达式零次或一次 
     .点 --- 匹配除“\r\n”之外的任何单个字符 
     \d --- 匹配一个数字字符。等价于[0-9] 
    \D --- 匹配一个非数字字符。等价于[^0-9]。 
     \w --- 等价于[A-Za-z_0-9]。 
     \转义 
      
     */  
  
    //匹配一个邮箱地址  
    //结构 (字母数字)@(字母数字)(.)(字母2~4个)  
    NSString *emailRegex = @"\\w+@\\w+\\.[A-Za-z]{2,4}";  
  
    NSPredicate *emailPredicate = [NSPredicate predicateWithFormat:@"name MATCHES %@",emailRegex];  
2.进行过滤,有两种方法,

一种是对数组进行过滤,把符合谓词条件的对象产生一个新的数组
一种是单独判断一个对象是否满足谓词条件,返回值为BOOL

 //过滤产生新的数组  
    self.searchArray =  [NSMutableArray arrayWithArray:[_dataArray filteredArrayUsingPredicate:testPredicate]];  
      
//对单个对象依次判断  
  if ([testPredicate evaluateWithObject:personDic])   
  {  
         //添加到搜索数组当中去  
         [_searchArray addObject:personDic];  
   }  

这里要注意一点,数组内放的对象可以是一个字典,也可以是一个类。

最后给出我写的完整的tableView上搜索框的使用

//  RootTableViewController.m      
#import "RootTableViewController.h"  
#import "Person.h"  
  
@interface RootTableViewController ()<UISearchResultsUpdating>  
  
@property (nonatomic,retain)NSMutableArray *dataArray;//全部数据数组  
@property (nonatomic,retain)NSMutableArray *searchArray;//搜索结果数组  
  
@property (nonatomic,retain)UISearchController *searchC;//搜索框  
  
@end  
  
@implementation RootTableViewController  
//懒加载  
-(NSMutableArray *)dataArray  
{  
    if (!_dataArray) {  
        _dataArray = [[NSMutableArray alloc]init];  
    }  
    return _dataArray;  
}  
-(NSMutableArray *)searchArray  
{  
    if (!_searchArray) {  
        _searchArray = [[NSMutableArray alloc]init];  
    }  
    return _searchArray;  
}  
    
- (void)viewDidLoad {  
    [super viewDidLoad];        
    self.navigationItem.title = @"search";  
      
    //添加搜索栏  
    _searchC = [[UISearchController alloc]initWithSearchResultsController:nil];        
    _searchC.searchBar.frame = CGRectMake(0, 0, 414, 50);  
      
    //更新代理  
    _searchC.searchResultsUpdater = self;  
      
    //搜索结果不变灰  
    _searchC.dimsBackgroundDuringPresentation = NO;  
      
    //便利初始化创建数据  
  
    NSArray *nameArray = [NSArray arrayWithObjects:@"王",@"李型剂",@"王青云",@"张菲菲",@"abe",@"ABe",@"aBS",@"wang@12.com", @"wan@126.cn",nil];  
  
    int ageList[] = {12,43,56,123,34,44,21,22,11};  
    for (int i = 0; i < 9; i++) {  
        Person *person = [Person personWithName:nameArray[i] Age:(NSInteger)ageList[i]];  
          
        //把全部人存到数组当中去  
        [self.dataArray addObject:person];  
    }  
      
    //添加到header  
    self.tableView.tableHeaderView = _searchC.searchBar;  
      
    //注册单元格  
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"CELL"];        
}    
//搜索代理方法,搜索框获得第一响应或内容变化时触发  
-(void)updateSearchResultsForSearchController:(UISearchController *)searchController  
{  
    //得到搜索框的文字  
    NSString* str = searchController.searchBar.text;  
    NSLog(@"%@",str);  
    //创建个谓词  
    // < > >= <= !=  
    NSPredicate *testPredicate = [NSPredicate predicateWithFormat:@"age < 50"];  
      
    //IN BETWEEN  
    NSPredicate *testPredicate_2 = [NSPredicate predicateWithFormat:@"age BETWEEN {50,100}"];  
    NSPredicate *testPredicate_3 = [NSPredicate predicateWithFormat:@"name IN{'王','张菲菲'}"];  
      
    //testPredicate  
//    @"name CONTAINS[cd] 'ang'"   //包含某个字符串  
//    @"name BEGINSWITH[c] 'sh'"     //以某个字符串开头  
//    @"name ENDSWITH[d] 'ang'"      //以某个字符串结束  
    NSPredicate *namePredicate = [NSPredicate predicateWithFormat:@"name CONTAINS %@",str];  
      
    //[c]不区分大小写 [d]无音调  [cd]两个都不要  
     NSPredicate *namePredicate_2 = [NSPredicate predicateWithFormat:@"name CONTAINS[c] %@ ",str];  
     
    //正则表达式      
    //匹配一个邮箱地址  
    //结构 (字母数字)@(字母数字)(.)(字母2~4个)  
    NSString *emailRegex = @"\\w+@\\w+\\.[A-Za-z]{2,4}";  
  
    NSPredicate *emailPredicate = [NSPredicate predicateWithFormat:@"name MATCHES %@",emailRegex];  
      
    //清空搜索数组  
    [_searchArray removeAllObjects];  
      
    //过滤,这里可以换不同的谓词进行试验  
    self.searchArray =  [NSMutableArray arrayWithArray:[_dataArray filteredArrayUsingPredicate:namePredicate_2]];  
      
    for (Person *person in _searchArray) {  
        NSLog(@"%@,%ld",person.name,person.age);  
    }        
    //刷新tableView  
    [self.tableView reloadData];  
  
}  
  
  
#pragma mark - Table view data source  
  
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {  
#warning Incomplete implementation, return the number of sections  
    return 1;  
}  
  
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {  
#warning Incomplete implementation, return the number of rows  
      
    //如果搜索框激活  
    if (_searchC.active) {  
        return _searchArray.count;  
    }  
    return _dataArray.count;  
}  
  
//cell的填充  
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {  
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CELL" forIndexPath:indexPath];  
      
    Person *onePerson = _dataArray[indexPath.row];  
      
    //如果搜索框激活  
    if (_searchC.active) {  
        onePerson = _searchArray[indexPath.row];  
    }  
      
    cell.textLabel.text = [NSString stringWithFormat:@"姓名:    %@, ----- 年龄:    %ld",onePerson.name,onePerson.age];  
      
    return cell;  
}    
@end  

person类
Person.h

#import <Foundation/Foundation.h>  
  
@interface Person : NSObject  
  
@property (nonatomic,retain)NSString *name;//姓名  
@property (nonatomic,assign)NSInteger age;//年龄  
  
//init  
-(instancetype)initWithName:(NSString*)name Age:(NSInteger)age;  
  
//便利  
+(instancetype)personWithName:(NSString*)name Age:(NSInteger)age;  
  
@end  

Person.m

#import "Person.h"  
  
@implementation Person  
//重写初始化方法  
-(instancetype)initWithName:(NSString *)name Age:(NSInteger)age  
{  
    self = [super init];  
    if (self) {  
        _age = age;  
        _name = name;  
    }  
    return self;  
}  
  
//便利构造器  
 +(instancetype)personWithName:(NSString *)name Age:(NSInteger)age  
{  
    Person *person = [[Person alloc]initWithName:name Age:age];  
    return person;  
}    
@end  

效果如下


再补充一下对字符串的正则过滤替换

NSRegularExpression *regular; 
//这个正则表达只允许汉字字母和常用标点
regular = [[NSRegularExpression alloc] initWithPattern:@"[^\\u4E00-\\u9FA5A-Za-z0-9-!,。、  ??\\t\\n\\r“”’‘:;!,.;:\"']" options:NSRegularExpressionCaseInsensitive error:nil]; str = [regular stringByReplacingMatchesInString:str options:NSRegularExpressionCaseInsensitive range:NSMakeRange(0, [str length]) withTemplate:@"-"];

//去除字符串中所有的空格及控制字符:
str = [str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet ]];
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,042评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,996评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,674评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,340评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,404评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,749评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,902评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,662评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,110评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,451评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,577评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,258评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,848评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,726评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,952评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,271评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,452评论 2 348

推荐阅读更多精彩内容