【IOS开发基础系列】UISearch专题

2023-10-16 11:41:39 浏览数 (1)

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 (nonatomicretainNSArray*dataArr;

//存储检索后的数据

@property (nonatomicretainNSArray*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

0 人点赞