一京景、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 ]];