iOS-個人整理20 - UISearchController搜索框與NSPredicate謂詞

一京景、UISearchController

搜索框的用處很大怎诫,就不用廢話了虐唠,在iOS8以前是用UISearchBar加代理實(shí)現(xiàn)的。
現(xiàn)在已經(jīng)廢棄少态,鼓勵使用新的UISearchController
首先遵守UISearchResultsUpdating協(xié)議

@interface RootTableViewController ()<UISearchResultsUpdating>  

//搜索代理方法城侧,搜索框獲得第一響應(yīng)或內(nèi)容變化時觸發(fā)  
-(void)updateSearchResultsForSearchController:(UISearchController *)searchController  
{  
   NSLog(@激活了搜索框");  
}  

再創(chuàng)建UISearchController,因?yàn)楹芏喾椒ǘ家獙λ阉骺蜻M(jìn)行判斷彼妻,寫成一個屬性

@property (nonatomic,retain)UISearchController *searchC;  

//初始化UISearchController嫌佑,把搜索框添加在tableView的headerView上
//添加搜索欄  
_searchC = [[UISearchController alloc]initWithSearchResultsController:nil];  
//設(shè)置frame  
_searchC.searchBar.frame = CGRectMake(0, 0, 414, 50);  
  
//更新代理  
_searchC.searchResultsUpdater = self;  
  
//搜索結(jié)果不變灰  
_searchC.dimsBackgroundDuringPresentation = NO;  
  
//添加到header  
self.tableView.tableHeaderView = _searchC.searchBar;  

這樣運(yùn)行就能看到搜索框了,點(diǎn)擊也會打印文字侨歉。

二屋摇、NSPredicate謂詞

光有搜索框沒什么卵用,還要有搜索功能幽邓,內(nèi)部的功能就需要謂詞來實(shí)現(xiàn)了
謂詞的功能很強(qiáng)大炮温,同時它還可以使用正則表達(dá)式,可以實(shí)現(xiàn)各種郵箱驗(yàn)證牵舵,手機(jī)號驗(yàn)證柒啤,以及各種查找功能。
使用的方法

1.創(chuàng)建謂詞
NSPredicate *testPredicate = [NSPredicate predicateWithFormat:@"age < 50"];  

謂詞的語法也很全面:
Format后面可以跟很多:
(1)比較運(yùn)算符>,<,==,>=,<=,!=可用于數(shù)值及字符串例:@"number > 100"
(2)范圍運(yùn)算符:IN畸颅、BETWEEN例:@"number BETWEEN {1,5}" @"address IN {'shanghai','beijing'}"
(3)字符串本身:SELF 例:@“SELF == ‘APPLE’"
(4)字符串相關(guān):

BEGINSWITH担巩、ENDSWITH、CONTAINS例:@"name CONTAIN[cd] 'ang'" //包含某個字符串
@"name BEGINSWITH[c] 'sh'" //以某個字符串開頭
@"name ENDSWITH[d] 'ang'" //以某個字符串結(jié)束
注:[c]不區(qū)分大小寫[d]不區(qū)分發(fā)音符號即沒有重音符號[cd]既不區(qū)分大小寫重斑,也不區(qū)分發(fā)音符號兵睛。

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

(6)正則表達(dá)式:MATCHES例:NSString *regex = @"^A.+e$"; //以A開頭,e結(jié)尾 @"name MATCHES %@",regex
用正則表達(dá)式簡單匹配一個郵箱

    /* 
   正則表達(dá)式常用的  
    ^ ---  匹配輸入字符串的開始位置 
    $ ---  匹配輸入字符串的結(jié)束位置 
    * --- 匹配前面的子表達(dá)式任意次 
     + --- 匹配前面的子表達(dá)式一次或多次 
     ? --- 匹配前面的子表達(dá)式零次或一次 
     .點(diǎn) --- 匹配除“\r\n”之外的任何單個字符 
     \d --- 匹配一個數(shù)字字符窥浪。等價于[0-9] 
    \D --- 匹配一個非數(shù)字字符祖很。等價于[^0-9]。 
     \w --- 等價于[A-Za-z_0-9]漾脂。 
     \轉(zhuǎn)義 
      
     */  
  
    //匹配一個郵箱地址  
    //結(jié)構(gòu) (字母數(shù)字)@(字母數(shù)字)(.)(字母2~4個)  
    NSString *emailRegex = @"\\w+@\\w+\\.[A-Za-z]{2,4}";  
  
    NSPredicate *emailPredicate = [NSPredicate predicateWithFormat:@"name MATCHES %@",emailRegex];  
2.進(jìn)行過濾假颇,有兩種方法,

一種是對數(shù)組進(jìn)行過濾骨稿,把符合謂詞條件的對象產(chǎn)生一個新的數(shù)組
一種是單獨(dú)判斷一個對象是否滿足謂詞條件笨鸡,返回值為BOOL

 //過濾產(chǎn)生新的數(shù)組  
    self.searchArray =  [NSMutableArray arrayWithArray:[_dataArray filteredArrayUsingPredicate:testPredicate]];  
      
//對單個對象依次判斷  
  if ([testPredicate evaluateWithObject:personDic])   
  {  
         //添加到搜索數(shù)組當(dāng)中去  
         [_searchArray addObject:personDic];  
   }  

這里要注意一點(diǎn)姜钳,數(shù)組內(nèi)放的對象可以是一個字典,也可以是一個類形耗。

最后給出我寫的完整的tableView上搜索框的使用

//  RootTableViewController.m      
#import "RootTableViewController.h"  
#import "Person.h"  
  
@interface RootTableViewController ()<UISearchResultsUpdating>  
  
@property (nonatomic,retain)NSMutableArray *dataArray;//全部數(shù)據(jù)數(shù)組  
@property (nonatomic,retain)NSMutableArray *searchArray;//搜索結(jié)果數(shù)組  
  
@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;  
      
    //搜索結(jié)果不變灰  
    _searchC.dimsBackgroundDuringPresentation = NO;  
      
    //便利初始化創(chuàng)建數(shù)據(jù)  
  
    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]];  
          
        //把全部人存到數(shù)組當(dāng)中去  
        [self.dataArray addObject:person];  
    }  
      
    //添加到header  
    self.tableView.tableHeaderView = _searchC.searchBar;  
      
    //注冊單元格  
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"CELL"];        
}    
//搜索代理方法哥桥,搜索框獲得第一響應(yīng)或內(nèi)容變化時觸發(fā)  
-(void)updateSearchResultsForSearchController:(UISearchController *)searchController  
{  
    //得到搜索框的文字  
    NSString* str = searchController.searchBar.text;  
    NSLog(@"%@",str);  
    //創(chuàng)建個謂詞  
    // < > >= <= !=  
    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'"      //以某個字符串結(jié)束  
    NSPredicate *namePredicate = [NSPredicate predicateWithFormat:@"name CONTAINS %@",str];  
      
    //[c]不區(qū)分大小寫 [d]無音調(diào)  [cd]兩個都不要  
     NSPredicate *namePredicate_2 = [NSPredicate predicateWithFormat:@"name CONTAINS[c] %@ ",str];  
     
    //正則表達(dá)式      
    //匹配一個郵箱地址  
    //結(jié)構(gòu) (字母數(shù)字)@(字母數(shù)字)(.)(字母2~4個)  
    NSString *emailRegex = @"\\w+@\\w+\\.[A-Za-z]{2,4}";  
  
    NSPredicate *emailPredicate = [NSPredicate predicateWithFormat:@"name MATCHES %@",emailRegex];  
      
    //清空搜索數(shù)組  
    [_searchArray removeAllObjects];  
      
    //過濾,這里可以換不同的謂詞進(jìn)行試驗(yàn)  
    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;  
}  
  
//便利構(gòu)造器  
 +(instancetype)personWithName:(NSString *)name Age:(NSInteger)age  
{  
    Person *person = [[Person alloc]initWithName:name Age:age];  
    return person;  
}    
@end  

效果如下


再補(bǔ)充一下對字符串的正則過濾替換

NSRegularExpression *regular; 
//這個正則表達(dá)只允許漢字字母和常用標(biāo)點(diǎn)
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 ]];
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末辱挥,一起剝皮案震驚了整個濱河市犁嗅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌晤碘,老刑警劉巖褂微,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異哼蛆,居然都是意外死亡蕊梧,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進(jìn)店門腮介,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人端衰,你說我怎么就攤上這事叠洗。” “怎么了旅东?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵灭抑,是天一觀的道長。 經(jīng)常有香客問我抵代,道長腾节,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任荤牍,我火速辦了婚禮案腺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘康吵。我一直安慰自己劈榨,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布晦嵌。 她就那樣靜靜地躺著同辣,像睡著了一般拷姿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上旱函,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天响巢,我揣著相機(jī)與錄音,去河邊找鬼棒妨。 笑死踪古,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的靶衍。 我是一名探鬼主播灾炭,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼颅眶!你這毒婦竟也來了蜈出?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤涛酗,失蹤者是張志新(化名)和其女友劉穎铡原,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體商叹,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡燕刻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了剖笙。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片卵洗。...
    茶點(diǎn)故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖弥咪,靈堂內(nèi)的尸體忽然破棺而出过蹂,到底是詐尸還是另有隱情,我是刑警寧澤聚至,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布酷勺,位于F島的核電站,受9級特大地震影響扳躬,放射性物質(zhì)發(fā)生泄漏脆诉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一贷币、第九天 我趴在偏房一處隱蔽的房頂上張望击胜。 院中可真熱鬧,春花似錦片择、人聲如沸潜的。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽啰挪。三九已至信不,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間亡呵,已是汗流浹背抽活。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留锰什,地道東北人下硕。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像汁胆,于是被迫代替她去往敵國和親梭姓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內(nèi)容