本文转载至 http://blog.sina.com.cn/s/blog_74e9d98d01019vji.html

 

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

首先我先讲下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,这样自定义出来的控件通过初始化之后,可以直接add到view中并呈现出来,

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

UISearchDisplayController对象,我如何把它显示到我应用的视图上呢?

研究了一会儿发现,只要把UISearchDisplayController的UISearchBar对象add到应用视图中就OK了!这就很奇怪了,为什么它的实现方式与之前自己的

实现不同呢,那之后再显示搜索结果的tableview的时候是如何展现到应用视图中的呢?通过测试发现:

原来UISearchDisplayController的UISearchBar对象初始化之后,默认进行了一些操作,如在UISearchDisplayController中实现UISearchBar的UISearchBarDelegate的相关方法,

以检测跟踪用户的“点击输入框”、“搜索关键字的变化”等一系列用户行为,然后UISearchDisplayController根据这些行为进行“弹出键盘”、“显示搜索结果tableView”等,而这些响应的

行为它并没有自己在类中写死掉,而是通过留出一个delegate给外部,让外部来实现这些具体的响应行为。至于它是怎样将结果tableView添加到应用视图中的,很明显,

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

这样就明白了。

由此,我们可以发现,苹果对控件的封装是严格按照MVC的模式来的,在此处,UISearchDisplayController就是model层,它不是View,他不受View的管制(如初始化后add到应用视图上),他应该是来管制视图的,

它只去处理逻辑数据(如获取用户输入的关键字并匹配出结果集),所以我们就可以明白了为什么应用视图只要add searchBar对象就行了的

尝试使用UISearchDisplayController及对苹果对控件封装习惯的理解的更多相关文章

  1. 控件使用经验-MVP模式+控件封装

    项目背景 几年前参与了一个面向学校的人事管理软件的开发,基于WinForm平台.今天主要想谈一谈其中关于控件的使用经验.这个项目我们大量使用了第三方控件.由于这个产品的生命周期很长,我们在设计时要考虑 ...

  2. 示例:WPF中Slider控件封装的缓冲播放进度条控件

    原文:示例:WPF中Slider控件封装的缓冲播放进度条控件 一.目的:模仿播放器播放进度条,支持缓冲任务功能 二.进度: 实现类似播放器中带缓存的播放样式(播放区域.缓冲区域.全部区域等样式) 实现 ...

  3. 玩转控件:封装Dev的LabelControl和TextEdit

    俗话说的好:"工欲善其事必先利其器",作为软件攻城狮也是同样道理,攻城狮开发的软件目的是简化客户的操作,让客户动动手指就可以完成很多事情,减少人力成本.这也是系统/软件存在的目的. ...

  4. 玩转控件:封装Dev的SearchLookupEdit

    鸣谢 随着前面几个章节对控件封装与扩展的分享,不少小伙伴儿们在作者公众号上反馈,并联系作者,表示通过这些系列和源码能学到不少细节上的东西,并运用到了自己的实际项目当中,也有不少伙伴儿反馈更好更优的处理 ...

  5. UI控件封装一般步骤

    封装 如果一个view内部的子控件比较多,一般会考虑自定义一个view,把它内部的子控件的创建屏蔽起来,不让外界关心 外界可以传入对应的模型数据给view,view拿到模型数据后给内部的子控件设置对应 ...

  6. [WP8.1UI控件编程]Windows Phone理解和运用ItemTemplate、ContentTemplate和DataTemplate

    2.2.5 ItemTemplate.ContentTemplate和DataTemplate 在理解ItemTemplate.ContentTemplate和DataTemplate的关系的之前,我 ...

  7. 对Delphi控件作用的新理解(控件本身的源代码就是一个很强的工业级源码)

    最近几天,对Delphi控件的含义有了一个新的理解.其实它不仅仅是给程序员提供功能的一个表层调用,控件本身的源代码就是一个很强的工业级源码.而且它的Main例子,往往就已经是半成品.而别的语言里没有那 ...

  8. Selenium webdriver 之select 控件封装,解决onchange问题

    使用webdriver的时候,select 控件经常会绑定onchange 事件,在selenium2.09 之前click 方法对onchange 事件有bug,2.09 以后修复了,但是根据经验也 ...

  9. Silverlight中在MVVM模式下对DatagridRow选择控件封装

    在项目中,凡是涉及到表格的地方用的最多的控件,自然少不了DataGrid的身影,它明了的展示各种数据让人十分喜欢.现在要实现一个功能,使DataGrid具有全选和项选中的功能,如果在传统后台代码中完成 ...

随机推荐

  1. Educational Codeforces Round 26

    Educational Codeforces Round 26 困到不行的场,等着中午显示器到了就可以美滋滋了 A. Text Volume time limit per test 1 second ...

  2. 牛客网Wannafly模拟赛

    A矩阵 时间限制:1秒 空间限制:131072K 题目描述 给出一个n * m的矩阵.让你从中发现一个最大的正方形.使得这样子的正方形在矩阵中出现了至少两次.输出最大正方形的边长. 输入描述: 第一行 ...

  3. 关于ul中li不对齐的问题

    将li中加入 overflow:hidden;    即可. 同时overflow:auto  可以控制滚动条的出现.

  4. Oracle学习笔记整理手册

    文章目录(1)Oracle正则匹配使用(2)Oracle修改有数据的数据字段类型(3)Oracle表数据回滚语句(4)sql筛选出记录数大于2的记录(5)oracle同义词(6)oracle内外连接( ...

  5. BZOJ 2780 [Spoj]8093 Sevenk Love Oimaster ——广义后缀自动机

    给定n个串m个询问,问每个串在n个串多少个串中出现了. 构建广义后缀自动机,(就是把所有字符串的后缀自动机合并起来)其实只需要add的时候注意一下就可以了. 然后对于每一个串,跑一边匹配,到达了now ...

  6. EC++学习笔记(一) 习惯c++

    条款01:c++多范式编程语言 条款02:尽量以 const, enum, inline 替换#define 1. 提供类型安全检查 2. 去除函数调用开销 3. 避免宏的二义性 const doub ...

  7. 【shell】shell编程(二)-运算符

    上篇我们学会了如何使用及定义变量.按照尿性,一般接下来就该学基本数据类型的运算了. 没错,本篇就仍是这么俗套的来讲讲这无聊但又必学的基本数据类型的运算了. 基本数据类型运算 操作符 符号 语义 描述 ...

  8. 用GDB远程调试android native程序

    上次写了几个native程序,想着如何调试,经过一阵子搜索和测试,终于完成了.有几个关键点: 1 gdb和gdbserver 因为这两个需要配套,建议使用同一个ndk下面的gdb和gdbserver ...

  9. JVM GC 相关

    http://blog.csdn.net/cutesource/article/details/5904501 http://www.cnblogs.com/dingyingsi/p/3760447. ...

  10. hdu3078 建层次树+在线LCA算法+排序

    题意:n个点,n-1条边构成无向树,每个节点有权,Q次询问,每次或问从a->b的最短路中,权第k大的值,/或者更新节点a的权, 思路:在线LCA,先dfs生成树0,标记出层数和fa[](每个节点 ...