做一个搜索框的Demo

打开手机,就会发现我们用的最多的就是TableView和搜索框了。

打开手机,从通知中心的搜索,APP store的搜索,通讯录的搜索,设置页面的搜索,照片搜索,信息搜索,再到打开每一个APP,都有的搜索。看了下,实现的需求类似,基本上都是输入关键字从网络接口上来搜索,只要点击过的都会保存到历史记录中,然后显示到历史记录的tableview中,下次可以直接点击然后搜索。可以清空单个记录或者所有的历史记录。还有一些APP还有热门搜索的标签。
所以,鉴于此,决定做一个Demo出来。

搜索框

对于搜索框可以用系统自带的UISearchBar,UISearchController,UISearchDisplayController,或者是自定义搜索框–把UIView和UITextField代理结合起来,

搜索功能

对于搜索功能的实现,
动态的:可以在输入一个字符,根据关键字去请求接口来返回数据加载在tableView上。
静态的:如果数据是本地的,或者是已经加载出来的数据中来搜索的话,可以用
NSPredicate来做过滤筛选出想要搜索的结果。

1
2
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", searchText];
self.searchResults = [self.items filteredArrayUsingPredicate:resultPredicate];

历史记录的存储

对于已经搜索过的历史记录可以选择的数据化存储有NSUserDefault,存在本地的Plist。还有就是Core Data的存储。
在APPdelegate中打印NSLog(@”%@”, NSHomeDirectory());记录本地存储的地址。
一般是/Users/peilinghui/Library/Developer/CoreSimulator/Devices/44CFA0DF-507C-4C90-A9E2-215F6706FB36/data/Containers/Data/Application/AA25A5E2-6E19-47F4-AB43-D4C73B1C3DE5。每次登陆都不一样额。

[[NSUserDefaults standardUserDefaults] objectForKey:obj];

对于多用户的历史记录的存储要拼接用户名

1
2
3
4
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [paths objectAtIndex:0];
// NSString *historyScheduleListPath = [docDir stringByAppendingPathComponent:@"historySchedule.plist"];
NSString *historyScheduleListPath = [docDir stringByAppendingPathComponent:[NSString stringWithFormat:@"history--%@.plist",UserDefaultsObjectForKey(LOGINUSERNAME)]];

tableView的数据源

  1. 如果是从接口查询数据的话,必然有历史记录的table和查询结果table。这个需要用到两个tableView两个数据源。通过判断来加载不同的数据源。
  2. 如果是从已经有的数据源中搜索结果,不论是静态的还是先从历史记录中搜索,用到谓词匹配的时候,也可以设置两个数据源来刷新一个table,或者是两个table两个数据源.

键盘的收起

  1. 当数据加载到tableview上,然后滚动时,要收起键盘:
1
2
3
4
5
#pragma mark - < UIScrollViewDelegate >
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[self.searchBar setShowsCancelButton:NO animated:YES];
[self.searchBar endEditing:YES];
}
  1. 点击searchBar的确定搜索和取消按钮的时候,要收起键盘:

[searchBar resignFirstResponder];

  1. 当进入后台的时候要收起键盘:不用view实现endEditing的方法
    [[[UIApplication sharedApplication] keyWindow] endEditing:YES];
    或者
    [[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];

  2. 点击背景View的时候收起键盘:

点击背景收起键盘可以实现view的

1
2
3
4
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event方法,然后执行view的- (BOOL)endEditing:(BOOL)force;方法。
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self.view endEditing:YES]; //实现该方法是需要注意view需要是继承UIControl而来的
}

在背景view上面加手势,添加UIButton或者view,然后在对应的点击事件的监听方法中实现resignFirstResponder或者endEditing。

1
2
3
4
5
6
7
8
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(keyboardHide:)];  
//设置成NO表示当前控件响应后会传播到其他控件上,默认为YES。
tapGestureRecognizer.cancelsTouchesInView = NO;
//将触摸事件添加到view上
[self.view addGestureRecognizer:tapGestureRecognizer];
-(void)keyboardHide:(UITapGestureRecognizer*)tap{
[textFiled resignFirstResponder];
}

Demo地址:https://github.com/peilinghui/BokeDemo/tree/master/%E7%A4%BA%E4%BE%8B%E6%90%9C%E7%B4%A2%E6%A1%86%E7%9A%84Table

文章目录
  1. 1. 搜索框
  2. 2. 搜索功能
  3. 3. 历史记录的存储
  4. 4. tableView的数据源
  5. 5. 键盘的收起
,