1 UISearchBar
UISearchBar是由两个subView组成的,一个是UISearchBarBackGround,另一个是UITextField.
1.1 代码示例
1. UISearchBar(效果如下:)
①创建UISearchBar对象
//初始化,定义frame
UISearchBar *bar = [[UISearchBar alloc] initWithFrame: CGRectMake(0, 50, self.view.frame.size.width, 80)];
//添加到控制器的视图上
[self.view addSubview: bar];
②UISerachBar的属性
//autocapitalizationType:包含4种类型,但是有时候键盘会屏蔽此属.
//1.autocapitalizationType————自动对输入文本对象进行大小写设置.
bar.autocapitalizationType = UITextAutocapitalizationTypeWords;
//2.autocorrectionType————自动对输入文本对象进行纠错
bar.autocorrectionType = UITextAutocorrectionTypeYes;
//3.设置title
bar.prompt = @"全部联系人";
//4.设置颜色
bar.tintColor = [UIColor purpleColor]; //渲染颜色
bar.barTintColor = [UIColor orangeColor]; //搜索条颜色
bar.backgroundColor = [UIColor purpleColor]; //背景颜色,因为毛玻璃效果(transulent).
//5.translucent————指定控件是否会有透视效果
bar.translucent = YES;
//6.scopeButtonTitles(范围buttonTitle)
bar.scopeButtonTitles = @[@"精确搜索",@"模糊搜索"];
bar.selectedScopeButtonIndex = 1;//通过下标指定默认选择的那个选择栏
//7.控制搜索栏下部的选择栏是否显示出来(需设置为YES 才能使用scopebar)
bar.showScopeBar = YES;
//8.设置搜索栏右边的按钮
bar.showsSearchResultsButton = YES;//向下的箭头
bar.showsCancelButton = YES; //取消按钮
bar.showsBookmarkButton = YES; //书签按钮
//9.提示内容
bar.placeholder = @"搜索";
//10.取消键盘操作
[searchBar resignFirstResponder];
//11.设置代理
//UISearchBar不执行搜索行为,必须使用delegate,当输入搜索文本、点击button按钮后,代理的方法
会完成搜索对应的操作。
//.控件的委托,委托要遵从UISearchBarDelegate协议,默认是nil
bar.delegate = self;
③代理要试实现的协议方法
1).输入编辑事件处理
– searchBar:textDidChange:
– searchBar:shouldChangeTextInRange:replacementText:
– searchBarShouldBeginEditing:
– searchBarTextDidBeginEditing:
– searchBarShouldEndEditing:
– searchBarTextDidEndEditing:
2).点击按钮事件处理
– searchBarBookmarkButtonClicked:
– searchBarCancelButtonClicked:
– searchBarSearchButtonClicked:
– searchBarResultsListButtonClicked:
3).点击Scope按钮事件处理
– searchBar: selectedScopeButtonIndexDidChange:
1.2 常用技巧
1.2.1 修改UISearchBar的背景
1.2.1.1 修改UISearchBar的背景颜色
UISearchBar是由两个subView组成的,一个是UISearchBarBackGround,另一个是UITextField.要IB中没有直接操作背景的属性。方法是直接将UISearchBarBackGround移去。
seachBar =[[UISearchBar alloc] init];
seachBar.backgroundColor = [UIColor clearColor];
for (UIView *subview in seachBar.subviews)
{
if ([subview isKindOfClass: NSClassFromString(@"UISearchBarBackground")])
{
[subview removeFromSuperview];
break;
}
}
第二种解决的方法:
[[[[[[self searchBar] subviews] objectAtIndex:0] subviews] objectAtIndex:0] removeFromSuperview];
1.2.1.2 为UISearchBar添加背景图片
UISearchBar *m_searchBar = [[UISearchBar alloc] initWithFrame: CGRectMake(0, 44, 320, 41)];
m_searchBar.delegate = self;
m_searchBar.barStyle = UIBarStyleBlackTranslucent;
m_searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
m_searchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
m_searchBar.placeholder= _(@"Search");
m_searchBar.keyboardType = UIKeyboardTypeDefault;
//为UISearchBar添加背景图片
UIView *segment = [m_searchBar.subviews objectAtIndex:0];
UIImageView *bgImage = [[UIImageView alloc] initWithImage: [UIImage imageNamed: @"Images/search_bar_bg.png"]];
[segment addSubview: bgImage];
//<---背景图片
[self.view addSubview: m_searchBar];
[m_searchBar release];
1.2.2 取消UISearchBar调用的键盘
[searchBar resignFirstResponder];
1.2.3 添加UISearchBar的两种方法:
1.2.3.1 普通视图添加
UISearchBar *mySearchBar= [[UISearchBar alloc]
initWithFrame:CGRectMake(0.0, 0.0, self.view.bounds.size.width, 45)];
mySearchBar.delegate = self;
mySearchBar.showsCancelButton = NO;
mySearchBar.barStyle = UIBarStyleDefault;
mySearchBar.placeholder = @"Enter Name or Categary";
mySearchBar.keyboardType = UIKeyboardTypeNamePhonePad;
[self.view addSubview: mySearchBar];
[mySearchBar release];
1.2.3.2 在tableview上添加
代码
//add Table
UITableView *myBeaconsTableView = [[UITableView alloc]
initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height-40)
style:UITableViewStylePlain];
myBeaconsTableView.backgroundColor = [UIColor whiteColor];
myBeaconsTableView.delegate = self;
myBeaconsTableView.dataSource = self;
[myBeaconsTableView setRowHeight:40];
// Add search bar
searchBar = [[UISearchBar alloc] initWithFrame: CGRectMake(0.0, 0.0, self.view.bounds.size.width, 40)];
searchBar.placeholder = @"Enter Name";
searchBar.delegate = self;
myBeaconsTableView.tableHeaderView = searchBar;
searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
searchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
[searchBar release];
[self.view addSubview: myBeaconsTableView];
[myBeaconsTableView release];
2 UISearchDisplayController使用
2.1 代码示例
2. UISearchDisplayController(注:iOS8以上已经弃用)
结合UISearchBar实现效果如下,实现搜索功能.
提示:检测Xcode系统版本代码如下:
[[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0 ? YES: NO;
①.创建对象
//需要创建UISearchBar对象,这里将对象都定义成了属性
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 40)];
//设置UISearchBar属性,上面有UISearchBar详细介绍.
self.searchBar.placeholder = @"enter province name";
self.searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
self.searchBar.autocapitalizationType = UITextAutocapitalizationTypeAllCharacters;
self.searchBar.scopeButtonTitles = [NSArray arrayWithObjects: @"All", @"A", @"B", @"C", @"D", nil];
self.searchBar.showsScopeBar = YES;
self.searchBar.keyboardType = UIKeyboardTypeNamePhonePad;
self.searchBar.showsBookmarkButton = YES;
//将seachBar作为控制器的透视图,视图控制器,继承UITableViewController
self.tableView.tableHeaderView = _searchBar;
//将UIsearchBar添加到UIdSearchDispalyController上
self.displayController = [[UISearchDisplayController alloc] initWithSearchBar: _searchBar contentsController: self];
注:searchBar————在searchdisplaycontroller初始化后,searchbar是不可修改的,是readonly属性的.
②配置UISearchDisplayController的属性
//active————是搜索界面可视化,默认为no,可用setActive方法设置.
self.displayController.active = YES;
// searchResultsDataSource————搜索结果的数据源,代理对象(UITableViewDataSource)
self.displayController.searchResultsDataSource = self;
//searchResultsDelegate————搜索结果的委托,服从协议UITableViewDelegate
self.displayController.searchResultsDelegate = self;
③实现
/*
searchDisplayController 自身有一个searchResultsTableView,所以在执行操作的时候首先要判断是否是搜索结果的tableView,如果是显示的就是搜索结果的数据,
如果不是,是TableView自身的view,则需要显示原始数据。
*/
if (tableView == self.tableView) {
return self.dataArray.count;
} else{
NSPredicate *predicate = [NSPredicate predicateWithFormat: @"self contains [cd] %@", self.searchBar.text];
self.arr = [[NSMutableArray alloc] initWithArray:[self.dataArray filteredArrayUsingPredicate: predicate]];
return self.arr.count;
}
④使用UISearchDisplayDelegate的委托方法进行搜索操作:
1).搜索状态改变事件处理方法:
– searchDisplayControllerWillBeginSearch:
– searchDisplayControllerDidBeginSearch:
– searchDisplayControllerWillEndSearch:
– searchDisplayControllerDidEndSearch:
2).装载和卸载tableview事件处理方法:
– searchDisplayController: didLoadSearchResultsTableView:
– searchDisplayController: willUnloadSearchResultsTableView:
3).显示和隐藏tableview事件处理方法:
– searchDisplayController:willShowSearchResultsTableView:
– searchDisplayController:didShowSearchResultsTableView:
– searchDisplayController:willHideSearchResultsTableView:
– searchDisplayController:didHideSearchResultsTableView:
4).搜索条件改变时响应事件处理方法:
– searchDisplayController:shouldReloadTableForSearchString:
2.2 开发技巧
2.2.1 重复使用SearchVC时要注意Cell重用问题,清空上一次的搜索结果cell
对于搜索结果表视图,IOS并不会随着SearchVC的退出而移除(应该是处于提高cell重用角度考虑),所以第二次进入视图时,默认其实还是显示的上次搜素结果cell,一定要注意清除状态。
另外,要注意表视图的cell重用问题,上下滑动时,下面的cell可能就是用的上面视图的某一个cell,里面数据都没有清空的,要记得全部更新。
- (BOOL) updateWithCityInfoObject: (HJCityInfoObject*) obj
{
BOOL isChoosed = obj.isChoosed;
self.textLabel.text = obj.cityName;
if (!isChoosed) {
HJCityObject * cObj = [HJManagerInstance getCityObjectByName: obj.cityName];
if(cObj) {
isChoosed =TRUE;
obj.isChoosed = TRUE;
}
}
if(isChoosed) {
if(!_choosedImageView)
{
_choosedImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed: @"ChoosedIcon"]];
[_choosedImageView setFrame: CGRectMake(self.frame.size.width - HJ_TableCell_X_Offset, (self.frame.size.height - HJ_AddCityCollectionCell_IsChoosedIcon_Height) / 2, HJ_AddCityCollectionCell_IsChoosedIcon_Height, HJ_AddCityCollectionCell_IsChoosedIcon_Width)];
[self addSubview: _choosedImageView];
}
}
else
{
if (_choosedImageView) {
[_choosedImageView removeFromSuperview];
_choosedImageView = nil;
}
}
return YES;
}
3 UISearchController
3.1 代码示例
3.1.1 效果图
3.UISearchController(iOS8新特性)
UISearchController实现和上述效果基本一致,适用于iOS8以上版本
实现如下图搜索效果
3.1.2 1)新建数据源属性
代码如下:
1)新建控制器,继承与UITableViewController,在extension中定义属性
//存储原来的数据
@property (nonatomic, retain) NSArray*dataArr;
//存储检索后的数据
@property (nonatomic, retain) NSArray*arr;
3.1.3 2)加载数据,懒加载
- (NSArray*)dataArr {
if (!_dataArr) {
self.dataArr = [NSArray arrayWithObjects:@"Allan", @"Abbbb", @"Acccc", @"Bccccc", @"Cddddffk", @"Cddkllll", @"Ekkflfl", @"Ekljljfg", @"Leslie", @"Mm", @"Meinv", @"Meihi", @"Catilin", @"Arron", @"211", @"232", @"243", @"264", @"285", @"106", @"311", @"432", @"543", @"664", @"785", @"806", nil nil];
}
return _dataArr;
}
//如果检索后的数据为空,将原有数据赋值给检索数据
- (NSArray*) arr {
if(!_arr) {
self.arr = self.dataArr;
}
return _arr;
}
3.1.4 3)加载UISearchController对象
- (void)viewDidLoad {
[super viewDidLoad];
//cell重用机制,调用系统的
[self.tableView registerClass: [UITableViewCell class] forCellReuseIdentifier: @"lock"];
//创建搜索条,将自身设置为展示结果的控制器
UISearchController *searchVC = [[UISearchController alloc] initWithSearchResultsController: nil];
//设置渲染颜色
searchVC.searchBar.tintColor = [UIColor orangeColor];
//设置状态条颜色
searchVC.searchBar.barTintColor = [UIColor orangeColor];
//设置开始搜索时背景显示与否(很重要)
searchVC.dimsBackgroundDuringPresentation = NO;
//适应整个屏幕
[searchVC.searchBar sizeToFit];
//设置显示搜索结果的控制器
searchVC.searchResultsUpdater = self; //协议(UISearchResultsUpdating)
//将搜索控制器的搜索条设置为页眉视图
self.tableView.tableHeaderView = searchVC.searchBar;
}
3.1.5 4)实现协议中的方法,必须实现
- (void) updateSearchResultsForSearchController: (UISearchController*)searchController
{
//谓词检测
NSPredicate *predicate = [NSPredicate predicateWithFormat: @"self contains [cd] %@", searchController.searchBar.text];
//将所有和搜索有关的内容存储到arr数组
self.arr = [NSMutableArray arrayWithArray: [self.dataArr filteredArrayUsingPredicate: predicate]];
//重新加载数据
[self.tableView reloadData];
}
3.1.6 5)设置UITabelViewController中的其它
#pragma mark - Table view data source
//设置有多少个分区
- (NSInteger) numberOfSectionsInTableView: (UITableView*)tableView {
// Return the number of sections.
return 1;
}
//每个分区有多少行数据
- (NSInteger) tableView: (UITableView *)tableView numberOfRowsInSection:
(NSInteger)section {
return self.arr.count;
}
- (UITableViewCell *) tableView: (UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath {
self.cell = [tableView dequeueReusableCellWithIdentifier: @"lock" forIndexPath: indexPath];
//设置cell上展示的内容,即搜索后的数据
self.cell.textLabel.text = self.arr[indexPath.row];
return self.cell;
}
注.以上是实现搜索框搜索空能.(当搜索内容为空时,返回的时所有数据,如果搜索内容为空,返回空时,需要进行其它修改操作.)
4 开发技巧
4.1 兼容IOS7、8并结合自定义导航条使用
4.1.1 核心思路
虽然UISearchController中也有Search bar变量,但是此界面中的Search bar必须自己新建定义,不能通过重用UISearchController. Search bar变量来实现,否则会出现很多布局与交互异常问题。
此界面中的Search bar只用于触发搜索操作,从而显示UISearchController页面。
使用时注意:在searchBarTextDidBeginEditing事件中必须将当前子视图上移44px(即移到导航条中),以便达到让用户觉得UISearchController界面中的Search bar就是此Search bar依上去的。
而用户退出UISearchController界面时,同样要记得重新设置此界面的布局,以便让用户觉得此Search bar是UISearchController界面中下移下来的。
4.1.2 初始化
4.1.2.1 通用初始化
float sysVer = [HJUtility getSystemVersion];
[self initSearchBarView];
if (sysVer <= 8.0) {
[self initSearchDisplayVC];
}
else
{
[self initSearchVC];
}
4.1.2.2 initSearchBar
- (void) initSearchBarView
{
if (!self.searchBar) {
_searchResultArray = [[NSArray alloc] init];
self.searchBar = [[UISearchBar alloc] initWithFrame: CGRectMake(0, 64, self.view.frame.size.width, 44)];
[self.searchBar setPlaceholder: @"搜索城市中文/拼音/字母"];
self.searchBar.delegate = self;
[self.view addSubview: _searchBar];
}
}
4.1.2.3 initSearchDisplayVC
- (void) initSearchDisplayVC
{
_searchDisplayVC = [[UISearchDisplayController alloc] initWithSearchBar: _searchBar contentsController: self];
_searchDisplayVC.delegate = self;
_searchDisplayVC.searchResultsDataSource = self;
_searchDisplayVC.searchResultsDelegate = self;
_searchDisplayVC.active = NO;
//注册
[_searchDisplayVC.searchResultsTableView registerClass: [HJCitySearchResultTableViewCell class] forCellReuseIdentifier: @"HJCitySearchResultTableViewCell"];
// [_searchDisplayVC setDisplaysSearchBarInNavigationBar: NO];
}
4.1.2.4 initSearchVC
- (void) initSearchVC
{
UIViewController * vc = [[UIViewController alloc] init];
[vc.view setFrame: CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
_resultTableView = [[UITableView alloc] initWithFrame: CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height) style: UITableViewStylePlain];
_resultTableView.dataSource = self;
_resultTableView.delegate = self;
//注册
[_resultTableView registerClass: [HJCitySearchResultTableViewCell class] forCellReuseIdentifier: @"HJCitySearchResultTableViewCell"];
[vc.view addSubview: _resultTableView];
[_searchVC.view setFrame: CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
_searchVC = [[UISearchController alloc] initWithSearchResultsController: vc];
_searchVC.delegate = self;
//设置开始搜索时背景显示与否(很重要)
_searchVC.dimsBackgroundDuringPresentation = YES;
[_searchVC setHidesNavigationBarDuringPresentation: YES];
//适应整个屏幕
[_searchVC.searchBar sizeToFit];
//设置显示搜索结果的控制器
_searchVC.searchResultsUpdater = self; //协议(UISearchResultsUpdating)
[_searchVC.searchBar setPlaceholder: @"搜索城市中文/拼音/字母"];
[_searchVC.searchBar setDelegate: self];
}
4.1.3 委托处理
4.1.3.1 UISearchBarDelegate委托处理
#pragma mark - UISearchBarDelegate 委托处理
- (void) searchBarTextDidBeginEditing: (UISearchBar*)searchBar
{
[self addResignFirstResponderGestureTap];
if (searchBar == _searchBar) {
if (_searchVC) {
[self.view addSubview: _searchVC.view];
[_searchVC setActive: YES];
[self layouSubViewsWhenSearchVCDisplay];
}
}
}
- (void)searchBar: (UISearchBar *)searchBar textDidChange: (NSString*)searchText
{
_searchResultArray = [HJDatabaseManagerInstance selectCityInfoObjectArrayFromTableWithQueryText: searchBar.text];
if (_searchDisplayVC) {
[_searchDisplayVC.searchResultsTableView reloadData];
}
else if (_searchVC){
[_resultTableView reloadData];
}
}
- (void) searchBarCancelButtonClicked: (UISearchBar*)searchBar
{
[self resetLayoutSubViews];
}
4.1.3.2 UISearchDisplayControllerDelegate
- (BOOL) searchDisplayController: (UISearchDisplayController *)controller
shouldReloadTableForSearchString: (NSString*)searchString{
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (BOOL) searchDisplayController: (UISearchDisplayController *)controller
shouldReloadTableForSearchScope: (NSInteger)searchOption{
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (void) searchDisplayControllerWillBeginSearch: (UISearchDisplayController*)controller
{
[self layouSubViewsWhenSearchVCDisplay];
}
- (void) searchDisplayControllerDidEndSearch: (UISearchDisplayController*)controller{
[self resetLayoutSubViews];
[_searchBar resignFirstResponder];
}
4.1.3.3 UISearchResultsUpdating委托
// Called when the search bar's text or scope has changed or when the search bar becomes first responder.
- (void) updateSearchResultsForSearchController: (UISearchController*)searchController
{
//已经在Searchbar委托方法中处理了
}
4.1.3.4 UISearchControllerDelegate
- (void) willPresentSearchController: (UISearchController*)searchController
{
}
- (void) willDismissSearchController: (UISearchController*)searchController
{
}
- (void) didDismissSearchController: (UISearchController*)searchController
{
if (_searchVC) {
[_searchVC setSearchResultsUpdater: nil];
if ( ![self.view.subviews containsObject: _searchBar]) {
[self.view addSubview: _searchBar];
[self.view bringSubviewToFront: _searchBar];
}
[_searchVC setActive: NO];
[_searchBar setDelegate: self];
[_searchBar setPlaceholder: @"搜索城市中文/拼音/字母"];
}
[self resetLayoutSubViews];
}
4.1.4 退出
- (void) closeView: (id)sender
{
if (_searchVC) {
[_searchVC.searchBar setDelegate: nil];
[_searchVC setDelegate: nil];
[_searchVC setSearchResultsUpdater: nil];
[_searchVC setActive: NO];
[_searchVC.view removeFromSuperview];
}
else if(_searchDisplayVC){
}
[_searchBar setDelegate: nil];
[self.navigationController.view removeFromSuperview];
[self.navigationController removeFromParentViewController];
}
4.1.5 输入栏外点击手势处理
- (void) addResignFirstResponderGestureTap
{
if (!_resignFirstResponderGesture) {
_resignFirstResponderGesture = [[UITapGestureRecognizer alloc] initWithTarget: self action: @selector(resignFirstResponderGestureTap)];
}
if (_searchDisplayVC) {
if (![_searchDisplayVC.searchResultsTableView.gestureRecognizers containsObject: _resignFirstResponderGesture]) {
[_searchDisplayVC.searchResultsTableView addGestureRecognizer: _resignFirstResponderGesture];
}
}
else if (_searchVC)
{
if (![_resultTableView.gestureRecognizers containsObject: _resignFirstResponderGesture]) {
[_resultTableView addGestureRecognizer: _resignFirstResponderGesture];
}
}
}
- (void) resignFirstResponderGestureTap
{
if (_searchDisplayVC) {
if ([_searchBar isFirstResponder]) {
[_searchBar resignFirstResponder];
[_searchDisplayVC.searchResultsTableView becomeFirstResponder];
[_searchDisplayVC.searchResultsTableView removeGestureRecognizer: _resignFirstResponderGesture];
}
}
else if(_searchVC)
{
if ([_searchVC.searchBar isFirstResponder]) {
[_searchVC.searchBar resignFirstResponder];
[_resultTableView becomeFirstResponder];
[_resultTableView removeGestureRecognizer: _resignFirstResponderGesture];
}
}
}
5 参考链接
UISearchBar和UISearchDisplayController的使用
http://www.cnblogs.com/langtianya/p/4114532.html
UISearchBar和UISearchDisplayController
http://www.cnblogs.com/VincentXue/archive/2012/08/30/2664119.html
SearchBar+SearchDisplayController实现实时搜索
http://www.cocoachina.com/bbs/read.php?tid=131433
ios UISearchDisplayController实现UITableView搜索功能
http://www.cnblogs.com/lesliefang/p/3929677.html
【学习ios之路:UI系列】(UISearchBar,UISearchDisplayController)和UISearchController(iOS8新特性)
http://blog.csdn.net/zfx5130/article/details/43371403
UISearchController基础使用
http://www.cnblogs.com/xiaojywuxy/p/4247963.html
Sample code to demonstrate using UISearchController In acollection view
https://github.com/dempseyatgithub/Sample-UISearchController
Insert a UISearchBar in IOS 8, Xcode 6
http://stackoverflow.com/questions/27632093/insert-a-uisearchbar-in-ios-8-xcode-6/27649289#27649289