UISearchDisplayController详解

原文链接

在之前做过的应用中,很多都有搜索这个功能,大部分情况下我都是只采用UISearchBar并结合UItableView来展示搜索结果,其 实IOS SDK中已经有自带的控件能帮助我们做好这些事,这就是UISearchDisplayController,当然这个控件也有一些不足之处,下面我就一 一道来。。

实现原理:

        UISearchDisplayController 不是一个viewController,其实它的父类就是NSObject  ,它里面就整合了 一个UISearchBar对象和一个UItableView对象,UISearchBar对象负责展示搜索输入框,UItableView对象负责展示 搜索出来的结果。然后,调用者在外部实现一些UISearchDisplayDelegate中的方法来做一些自定义的处理,这个protocol中有很 多方法,其中最重要的就是

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString  此方法获取用户输入的关键字searchString,然后开发者处理出搜索结果并返回YES,表示重新reload  UItableView对象

使用方法:

.h文件

#import

 

@interface ViewController : UIViewController{

    UISearchDisplayController *searchDisplayController;

    NSArray *_searchResults;  //存放搜索结果的数组

}

 

@property (retain, nonatomic) IBOutlet CustomSearchDisplayController *searchDisplayController;

@property (nonatomic, copy) NSArray *searchResults;

 

@end

 

.m文件:

#pragma mark tableView

 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

{

    NSInteger rows = 0;

    if ([tableView  isEqual:self.searchDisplayController.searchResultsTableView]){ //表示当前tableView显示的是搜索结果

        rows = [self.searchResults count];

    }else{

        //此处可以展示所有的数据,一般本地搜索可用到,如电话簿

    }   

 

    return rows;

}

 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {

        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

    }  

 

   

 

    if ([tableView isEqual:self.searchDisplayController.searchResultsTableView]){

        cell.textLabel.text = [self.searchResults objectAtIndex:indexPath.row];

    }else{

       // cell.textLabel.text = [self.allItems objectAtIndex:indexPath.row];

    }  

 

    return cell;

}

 

#pragma mark - UISearchDisplayController delegate methods

 

-(BOOL)searchDisplayController:(UISearchDisplayController *)controller  shouldReloadTableForSearchString:(NSString *)searchString {

    //根据用户的输入的关键字searchString,处理出搜索结果(可以是本地搜索,可以是从服务器请求过来的数据)到数组self.searchResults

    return YES; //返回yes,重新加载tableView对象

}

 

至此,UISearchDisplayController控件的大致使用方法就是如此了。

 

不足之处

当使用UISearchDisplayController之后,你是否发现,当键盘弹出来的时候,会默认把navagationBar给隐藏起来,如果说不需要隐藏navagationBar,最好的处理方式就是重写UISearchDisplayController-(void)setActive:(BOOL)visible animated:(BOOL)animated方法

    首先,自定义一个类CustomSearchDisplayController,继承自UISearchDisplayController,然后在.m文件中重写该方法,并在该方法中主动显示navagationBar

    #import "CustomSearchDisplayController.h"

 

    @implementation CustomSearchDisplayController

 

    -(void)setActive:(BOOL)visible animated:(BOOL)animated

   {

     [super setActive:visible animated:animated];

     [self.searchContentsController.navigationController setNavigationBarHidden: NO animated: NO];

   }

 

   @end

 

   当没有匹配的结果时,默认会在tableView上显示一个“No Result”的标签,如果说想自定义这个标签,可以在tableview中循环遍历出该标签,然后按照你的想法去设置

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString

{

[self filterContentForSearchText:searchString];

if ([filteredListPinYin count] == 0) {

UITableView *tableView1 = self.searchDisplayController.searchResultsTableView;

for( UIView *subview in tableView1.subviews ) {

if( [subview class] == [UILabel class] ) {

UILabel *lbl = (UILabel*)subview; // sv changed to subview.

lbl.text = @”没有结果”;

}

}

}

// Return YES to cause the search result table view to be reloaded.

    return YES;

}

       另外,由于UISearchDisplayController里的UISearchBar对象和UITableView对象都是可访问的,因此就给我们很多便利可以随意的更改其在UI上的显示效果


苹果对控件封装习惯的理解:

      之前我做过的控件封装,基本上都是继承自UIView或是UIViewController,这样自定义出来的控件通过初始化之后,可以直接addview中并呈现出来,

      但是仔细看看UISearchDisplayController,他并不是一个视图类的对象,当通过调用初始化函数并指定delegate之后,我突然间陷入了无路之境,我现在已经创建好UISearchDisplayController对象,我如何把它显示到我应用的视图上呢?

      研究了一会儿发现,只要把UISearchDisplayControllerUISearchBar对象add到应用视图中就OK了!这就很奇怪了,为什么它的实现方式与之前自己的实现不同呢,那之后再显示搜索结果的tableview的时候是如何展现到应用视图中的呢?通过测试发现:

      原来UISearchDisplayControllerUISearchBar对象初始化之后,默认进行了一些操作,如UISearchDisplayController中实现UISearchBarUISearchBarDelegate的相关方法以检测跟踪用户的点击输入框搜索关键字的变化等一系列用户行为,然后UISearchDisplayController根据这些行为进行弹出键盘显示搜索结果tableView”等,而这些响应的行为它并没有自己在类中写死掉,而是通过留出一个delegate给外部,让外部来实现这些具体的响应行为。至于它是怎样将结果tableView添加到应用视图中的,很明显,

初始化函数:- (id)initWithSearchBar:(UISearchBar *)searchBar contentsController:(UIViewController *)viewController;中有个contentsController变量就是指的应用视图congtoller

这样就明白了。

     由此,我们可以发现,苹果对控件的封装是严格按照MVC的模式来的,在此处,UISearchDisplayController就是model层,它不是View,他不受View的管制(如初始化后add到应用视图上),他应该是来管制视图的,它只去处理逻辑数据(如获取用户输入的关键字并匹配出结果集),所以我们就可以明白了为什么应用视图只要add searchBar对象就行了的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值