IOS中Table View控件练习(表视图,自定义cell,分组,索引,搜索)

之前两篇博客简单学习了Picker view控件的使用,接下来再学习IOS应用中很重要的一个视图--表视图。

在表视图中,每个表视图都是UITableView的一个实例,每个可见行都是UITableViewCell的一个实例。

表视图有两种基本格式,分组的表和普通表,普通表可以实现索引,实现了索引的表成为索引表。(PS.技术上,分组表也可以实现索引,不过好像苹果的设计规范中不支持)

 目录

一个简单的表视图

自定义Cell的tableView

表视图分组和索引

表视图添加搜索栏

一个简单的表视图应用

界面设计:

向storyboard中拖一个table view控件,他会自动占满屏幕,至于约束,可以自己创建,记得设置tableview的tag为1,后面会用到。

table view的outlets中会有dataSourcedelegate两个设置项,按住每个设置项后面的空心圆,拖向storyboard中的controller按钮,完成关联。

代码讲解:

首先要在对应控制器的.h文件中实现UITableViewDataSourceUITableViewDelegate两个协议。

在.m文件中首先定义一个nsarray类型的属性,这个属性用来存放tableview要显示的数据,并且在viewDidLoad方法中给nsarray赋值。

在viewDidLoad方法中还需要做的是把tableview的顶部向下偏移一定数量来美化界面(算不得美化,如果不做这一步处理,tableview顶部会紧挨着状态栏,很难看<( ̄▽ ̄)> 哇哈哈…)

    UITableView* tableView = (id)[self.view viewWithTag:1];//通过tag获取控件
    UIEdgeInsets contentInset = tableView.contentInset;
    contentInset.top = 20;
    [tableView setContentInset:contentInset];

然后实现两个委托方法,一个是- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section,返回这个table的行数,

另一个是- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath,这个方法会返回指定行的TableViewCell。

首先看看这个方法的参数,第一个参数是一个tableview,表示触发这个方法的table。第二个参数是NSIndexPath类型的值,这个类型有两个主要的属性,section和row,组和行。

创建一个UITableViewCell对象,此处使用的dequeueReusableCellWithIdentifier:方法,这个方法会返回一个可以重用的cell,也有可能返回nil

所以我们要判断返回值,如果返回值为nil,就需要实例化一个cell

有了cell,就能设置cell要显示的文本

cell.textLabel.text = self.dwarves[indexPath.row];

不只可以设置文本,还可以设置图标

    UIImage* image = [UIImage imageNamed:@"star"];
    cell.imageView.image = image;

imageView除了有image属性外,还有一个hightedImage属性,可以自己设置。

这个程序让所有的行都使用了相同的图标,我们可以根据indexPath中的section和row设置每行的专属图标

行选择事件:

行的选择事件需要在一个委托方法中处理,这个方法是

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

这个方法在行被选择之后调用,可以在这个方法内通过indexPath参数确定所选的组和行,进一步处理,处理完成之后把该行取消选择状态

[tableView deselectRowAtIndexPath:indexPath animated:YES];

上一个方法是在行被选择之后调用,还有一个委托方法会在行被选择之前就调用,这个方法是

-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath

这个方法里也可以通过indexPath判断用户点击的组和行,进而实现禁止选择某一行。返回nil就是禁止选择了某一行

完整代码:

 1 //
 2 //  ViewController.m
 3 //  Simple Table
 4 //
 5 //  Created by 张光发 on 15/10/19.
 6 //  Copyright (c) 2015年 张光发. All rights reserved.
 7 //
 8 
 9 #import "ViewController.h"
10 
11 @interface ViewController ()
12 @property (strong, nonatomic) NSArray* dwarves;
13 @end
14 
15 @implementation ViewController
16 
17 - (void)viewDidLoad
18 {
19     [super viewDidLoad];
20     self.dwarves = @[ @"Sleepy", @"Sneezy", @"Bashful", @"Happy", @"Doc", @"Grumpy", @"Dopey", @"Thorin", @"Dorin", @"Nori", @"Ori", @"Balin", @"Dwalin", @"Fili", @"Kili", @"Oin", @"Gloin", @"Bifur", @"Bofur", @"Bombur" ];
21     UITableView* tableView = (id)[self.view viewWithTag:1];
22     UIEdgeInsets contentInset = tableView.contentInset;
23     contentInset.top = 20;
24     [tableView setContentInset:contentInset];
25 }
26 
27 - (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
28 {
29     return [self.dwarves count];
30 }
31 
32 - (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
33 {
34     static NSString* SimpleTableIndetifier = @"SimpleTableIdentfier";
35     UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:SimpleTableIndetifier];
36     if (cell == nil) {
37         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SimpleTableIndetifier];
38     }
39     UIImage* image = [UIImage imageNamed:@"star"];
40     cell.imageView.image = image;
41     cell.textLabel.text = self.dwarves[indexPath.row];
42     if (indexPath.row<7) {
43         cell.detailTextLabel.text=@"MR. dIDSNEY";
44     }else{
45         cell.detailTextLabel.text=@"mr. Tolkien";
46     }
47     return cell;
48 }
49 
50 //!!!: 选中之前
51 -(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
52 {
53     if (indexPath.row==0) {
54         return nil;
55     }else{
56         return indexPath;
57     }
58 }
59 //!!!: 行被选择时调用
60 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
61 {
62     NSString *rowValue=self.dwarves[indexPath.row];
63     NSString *message=[[NSString alloc] initWithFormat:@"你选择的是%@",rowValue];
64     UIAlertView *alert=[[UIAlertView alloc] initWithTitle:@"Row Selected!" message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
65     [alert show];
66     //取消行选中状态
67     [tableView deselectRowAtIndexPath:indexPath animated:YES];
68 }
69 @end
View Code

 

自定义Cell的tableView

思路:

两种自定义cell的方式,一种是使用代码布局的,一种是从nib文件加载,两种方式最终实现的效果是一样的

实现的原理就是单独设计Cell的界面,然后把设计好的cell界面当做子view使用,记着设计好公开属性或接口,让tableview赋值

使用代码布局的方式:

新建一个cocoa touch class,命名为NameAndColorCell,subclass of选择UITableViewCell

在.h文件公开两个NSString属性,name和color

在.m文件中设计两个私有UILable属性,nameLabel和colorLabel,然后实现一个方法

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString*)reuseIdentifier

在tableview加载cell时会调用这个方法,这个方法实现的内容就是布局

首先初始化self,因为本类继承自UITableViewCell,所以初始化self的方法就是调用父类中的初始化方法

self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];

然后添加2个uilabel,并设置NameAndColorCell类中的所有uilabel(包括2个私有的uilabel),并把它们添加到self.contentView中,因为contentView管理着cell的所有子视图,所以要添加到这里,而不是直接添加到cell。

重写setName:(NSString *)name和setColor:(NSString *)color方法,

判断如果当前实例的公开属性_name不等于要设置的name,就设置私有属性nameLabel的text为name,color同理。文字描述有点绕,看看代码吧

- (void)setName:(NSString*)name
{
    if (![name isEqualToString:_name]) {
//为什么不直接设置nameLabel.text=name?请各路大哥解答,感激不尽 _name
= [name copy]; self.nameLabel.text = _name; } }

这样cell子视图就写完了,下面要编写主控制器中的代码。

主控制器.m文件要引用cell类,使用

#import "NameAndColorCell.h"

定义一个静态nsstring,后面会用到多次,防止拼写错误,内容可以自己定义

static NSString *CellTableIdentifier = @"CellTableIdentifier";

定义一个nsarray类型的属性,作为tableview的数据,并在viewDidLoad中给这个属性赋值

除此之外,还应该在viewDidLoad方法中告诉tableview应该怎样加载cell

  UITableView *tableView = (id)[self.view viewWithTag:1];
  //???: 告诉tableview应该从哪里加载cell
  [tableView registerClass:[NameAndColorCell class]
      forCellReuseIdentifier:CellTableIdentifier];

记得把tableview的顶部向下偏移一段距离,要不然很丑~>_<~ 

最后记得实现两个数据源方法,

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

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

第二个方法是返回指定indexpath的cell,

因为我们是自定义cell,所以初始化一个cell类,

NameAndColorCell *cell =
      [tableView dequeueReusableCellWithIdentifier:CellTableIdentifier forIndexPath:indexPath];

然后根据indexPath.row获取行数据,赋值给cell中的name和color

  NSDictionary *rowData = self.computers[indexPath.row];
  cell.name = rowData[@"Name"];
  cell.color = rowData[@"Color"];

最后返回这个cell实例既可。

 

完整代码:

主控制器.m

 1 //
 2 //  ViewController.m
 3 //  Cells
 4 //
 5 //  Created by 张光发 on 15/10/20.
 6 //  Copyright (c) 2015年 张光发. All rights reserved.
 7 //
 8 
 9 #import "ViewController.h"
10 #import "NameAndColorCell.h"
11 
12 static NSString *CellTableIdentifier = @"CellTableIdentifier";
13 
14 @interface ViewController ()
15 @property(copy, nonatomic) NSArray *computers;
16 @end
17 
18 @implementation ViewController
19 
20 - (void)viewDidLoad {
21   [super viewDidLoad];
22   self.computers = @[
23     @{
24       @"Name" : @"MacBook Air",
25       @"Color" : @"Silver"
26     },
27     @{
28       @"Name" : @"MacBook Pro",
29       @"Color" : @"Silver"
30     },
31     @{
32       @"Name" : @"iMac",
33       @"Color" : @"Silver"
34     },
35     @{
36       @"Name" : @"Mac Mini",
37       @"Color" : @"Silver"
38     },
39     @{
40       @"Name" : @"Mac Pro",
41       @"Color" : @"Black"
42     }
43   ];
44   UITableView *tableView = (id)[self.view viewWithTag:1];
45   //???: 告诉tableview应该从哪里加载cell
46   [tableView registerClass:[NameAndColorCell class]
47       forCellReuseIdentifier:CellTableIdentifier];
48 
49   UIEdgeInsets contentInset = tableView.contentInset;
50   contentInset.top = 20;
51   [tableView setContentInset:contentInset];
52 }
53 
54 - (NSInteger)tableView:(UITableView *)tableView
55  numberOfRowsInSection:(NSInteger)section {
56   return [self.computers count];
57 }
58 
59 - (UITableViewCell *)tableView:(UITableView *)tableView
60          cellForRowAtIndexPath:(NSIndexPath *)indexPath {
61   NameAndColorCell *cell =
62       [tableView dequeueReusableCellWithIdentifier:CellTableIdentifier
63                                       forIndexPath:indexPath];
64   NSDictionary *rowData = self.computers[indexPath.row];
65 
66   cell.name = rowData[@"Name"];
67   cell.color = rowData[@"Color"];
68 
69   return cell;
70 }
71 
72 @end
View Code

cell视图.m

 1 //
 2 //  NameAndColorCell.m
 3 //
 4 //
 5 //  Created by 张光发 on 15/10/20.
 6 //
 7 //
 8 
 9 #import "NameAndColorCell.h"
10 @interface NameAndColorCell ()
11 @property (strong, nonatomic) UILabel* nameLabel;
12 @property (strong, nonatomic) UILabel* colorLabel;
13 @end
14 
15 @implementation NameAndColorCell
16 
17 - (void)awakeFromNib
18 {
19     // Initialization code
20 }
21 
22 - (void)setSelected:(BOOL)selected animated:(BOOL)animated
23 {
24     [super setSelected:selected animated:animated];
25 
26     // Configure the view for the selected state
27 }
28 
29 - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString*)reuseIdentifier
30 {
31     self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
32     if (self) {
33         CGRect nameLabelRect = CGRectMake(0, 5, 70, 15);
34         UILabel* nameMarker = [[UILabel alloc] initWithFrame:nameLabelRect];
35         nameMarker.textAlignment = NSTextAlignmentRight;
36         nameMarker.text = @"Name";
37         nameMarker.font = [UIFont boldSystemFontOfSize:12];
38         [self.contentView addSubview:nameMarker];
39 
40         CGRect colorLabelRect = CGRectMake(0, 25, 70, 15);
41         UILabel* colorMarker = [[UILabel alloc] initWithFrame:colorLabelRect];
42         colorMarker.textAlignment = NSTextAlignmentRight;
43         colorMarker.text = @"Color";
44         colorMarker.font = [UIFont boldSystemFontOfSize:12];
45         [self.contentView addSubview:colorMarker];
46 
47         CGRect nameValueRect = CGRectMake(80, 5, 200, 15);
48         _nameLabel = [[UILabel alloc] initWithFrame:nameValueRect];
49         [self.contentView addSubview:_nameLabel];
50 
51         CGRect colorValueRect = CGRectMake(80, 25, 200, 15);
52         _colorLabel = [[UILabel alloc] initWithFrame:colorValueRect];
53         [self.contentView addSubview:_colorLabel];
54     }
55     return self;
56 }
57 
58 - (void)setName:(NSString*)name
59 {
60     if (![name isEqualToString:_name]) {
61         _name = [name copy];
62         self.nameLabel.text = _name;
63     }
64 }
65 - (void)setColor:(NSString*)color
66 {
67     if (![color isEqualToString:_color]) {
68         _color = [color copy];
69         self.colorLabel.text = _color;
70     }
71 }
72 @end
View Code

 

使用nib布局:

首先把上面的子视图.m文件中定义的两个私有uilabel改为接口,既IBOutlet

在上面的基础上,添加一个user interface组中empty类型的文件,并命名为NameAndColorCell,

这个nib文件是空白的,首先在文件检查器中取消自动布局。

拖一个tableviewcell,并在属性检查器中设置identifier为"CellTableIdentifier",这是为了和上面的代码一致。

拖出4个uilabel,排列并设置好字体等信息。

在身份检查器中设置class为NameAndColorCell.在关联检查器中应该就能看到第一步更改的两个输出接口了,按住后面的空心圆拖到对应的uilabel上。

 

这些操作的意义就是代替了子视图.m文件中的

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString*)reuseIdentifier方法。

在主视图.m文件中的viewDidLoad方法中删除之前的

[tableView registerClass:[NameAndColorCell class] forCellReuseIdentifier:CellTableIdentifier];

因为这是使用代码布局的,我们现在要使用nib文件布局,所以修改为

UINib *nib=[UINib nibWithNibName:@"NameAndColorCell" bundle:nil];
[tableView registerNib:nib forCellReuseIdentifier:CellTableIdentifier];

其他的不变,这样就是使用了nib文件布局。因为代码改动较少,而且不难,这里就不贴源码了。

 

 

表视图分组和索引

界面布局:

使用single view application 模板,在main.storyboard中拖一个tableview放在场景中,设置约束,在属性检查器中设置style为grouped,关联delegate和dataSource关联。

 

代码讲解:

在.h文件中继承UITableViewDelegate,UITableViewDataSource协议。

这次例子用到的数据太多,提供一个plist,点击下载

这个plist文件中按照字母分组,每个字母下有许多对应字母开头的名字。

定义一个静态nsstring,用作cell的标识,内容随意。

定义两个属性,一个是NSDictionary *name,另一个是NSArray* keys。

name加载的所有数据,keys只存放了组名称。

在viewDidLoad中要做的工作就是给tableview注册cell,把plist文件中的数据加载到name和keys中。

然后实现几个UITableViewDataSource中的方法,来设置tableview的一些属性

 1 //TODO: 返回组数
 2 - (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
 3 {
 4     return [self.names count];
 5 }
 6 
 7 //TODO: 返回指定组的行数
 8 - (NSInteger)tableView:(UITableView*)tableView
 9  numberOfRowsInSection:(NSInteger)section
10 {
11     NSString* key = self.keys[section];
12     NSArray* nameSection = self.names[key];
13     return [nameSection count];
14 }
15 
16 //TODO: 返回指定组的组标题
17 - (NSString*)tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section
18 {
19     return self.keys[section];
20 }
21 
22 //TODO: 返回指定位置的cell
23 - (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
24 {
25     UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier forIndexPath:indexPath];
26     //获取组名
27     NSString* key = self.keys[indexPath.section];
28     //获取对应组名下的所有名字
29     NSArray* nameSection = self.names[key];
30     //获取并设置指定行的名字
31     cell.textLabel.text = nameSection[indexPath.row];
32     return cell;
33 }
View Code

这样就完成了表视图的分组,主要还是数据。

添加索引:

把tableview的style设置为plain,实现另一个UITableViewDataSource中的方法

- (NSArray*)sectionIndexTitlesForTableView:(UITableView*)tableView

这个方法就给tableview添加了索引,返回的nsarray就是索引的内容,所以这里返回keys就可以了。

 

程序优化:

tableview的style成为plain之后,又出现了之前状态栏干扰问题,所以要在viewDidLoad中判断tableview的style,如果是plain就让tableview向下偏移一定距离。

另一个问题是列表滚动的时候,内容会穿过状态栏,效果很难看,所以我们添加一个透明的view放在状态栏,这样就能大大美化这个现象。

UIView* backView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 20)];
backView.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.9];
[self.view addSubview:backView];

 

完整代码:

 1 //
 2 //  ViewController.m
 3 //  Sections
 4 //
 5 //  Created by 张光发 on 15/10/22.
 6 //  Copyright (c) 2015年 张光发. All rights reserved.
 7 //
 8 
 9 #import "ViewController.h"
10 static NSString* SectionsTableIdentifier = @"SectionTableIdentifier";
11 
12 @interface ViewController ()
13 @property (copy, nonatomic) NSDictionary* names;
14 @property (copy, nonatomic) NSArray* keys;
15 @end
16 
17 @implementation ViewController
18 
19 - (void)viewDidLoad
20 {
21     [super viewDidLoad];
22     
23     UITableView* tableView = (id)[self.view viewWithTag:1];
24     [tableView registerClass:[UITableViewCell class]
25         forCellReuseIdentifier:SectionsTableIdentifier];
26     
27     NSString* path =
28         [[NSBundle mainBundle] pathForResource:@"sortednames"
29                                         ofType:@"plist"];
30     self.names = [NSDictionary dictionaryWithContentsOfFile:path];
31     self.keys =
32         [[self.names allKeys] sortedArrayUsingSelector:@selector(compare:)];
33 
34     if (tableView.style == UITableViewStylePlain) {
35         UIEdgeInsets contentInset = tableView.contentInset;
36         contentInset.top = 20;
37         [tableView setContentInset:contentInset];
38 
39         UIView* backView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 20)];
40         backView.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.9];
41         [self.view addSubview:backView];
42     }
43 }
44 
45 //TODO: 返回组数
46 - (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
47 {
48     return [self.names count];
49 }
50 
51 //TODO: 返回指定组的行数
52 - (NSInteger)tableView:(UITableView*)tableView
53  numberOfRowsInSection:(NSInteger)section
54 {
55     NSString* key = self.keys[section];
56     NSArray* nameSection = self.names[key];
57     return [nameSection count];
58 }
59 
60 //TODO: 返回指定组的组标题
61 - (NSString*)tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section
62 {
63     return self.keys[section];
64 }
65 
66 //TODO: 返回指定位置的cell
67 - (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
68 {
69     UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier forIndexPath:indexPath];
70     //获取组名
71     NSString* key = self.keys[indexPath.section];
72     //获取对应组名下的所有名字
73     NSArray* nameSection = self.names[key];
74     //获取并设置指定行的名字
75     cell.textLabel.text = nameSection[indexPath.row];
76     return cell;
77 }
78 
79 //TODO: 增加索引,返回索引内容
80 - (NSArray*)sectionIndexTitlesForTableView:(UITableView*)tableView
81 {
82     return self.keys;
83 }
84 @end
View Code

 

 

表视图添加搜索栏

我看完课本上的搜索发现课本用的过时的搜索方法,既uisearchdisplaycontroller和uisearchbar配合的方法,这样的方法在ios8已经不推荐了,所以我在查找新的方法,使用uisearchcontroller代替,今晚偷懒看个电影,还没整理好,明天周六更新^-^ 

对了,明天去鼓楼小吃街吃卤煮、爆肚、炒肝,各位不要羡慕哟,哈哈

------------------------------------------------------华丽丽的分割线------------------------------------------------------

今天去鼓楼转了转,吃了不少好吃的,看到不少漂亮妹子 Y^o^Y 

晚上回来没忘了昨天的搜索,百度之后整理了一下,写下来吧,使用UISearcherController,原因上面说到了。

主要参考了推酷上一篇文章,文章链接

 

界面设计方面和之前的一样,只需要一个tableview,这里就不再说了。

代码讲解:

.h文件中,继承UITableViewDataSource,UITableViewDelegate,UISearchBarDelegate,UISearchResultsUpdating 4个协议。

.m文件中定义3个属性,NSMutableArray* dataList,NSMutableArray* searchList,UISearchController* searchController。

其中,dataList是存储的所有数据,searchList存储的搜索结果,sracherController就是实现搜索功能要用到的。

在viewDidLoad方法中,首先生成数据,设置tableview的偏移量,添加状态栏遮罩(上面说到了),

然后初始化searcherController,并设置一些属性

1     _searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
2     //显示搜索结果的控制器,必要
3     _searchController.searchResultsUpdater = self;
4     //搜索时底层内容是否显示灰色
5     _searchController.dimsBackgroundDuringPresentation = NO;
6     //搜索时导航栏是否隐藏
7     _searchController.hidesNavigationBarDuringPresentation = NO;
8     //搜索栏的位置、大小信息,必要
9     _searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, self.searchController.searchBar.frame.origin.y, self.searchController.searchBar.frame.size.width, 44.0);
View Code

之后就是实现一些代理方法,其中最重要的一个是

- (void)updateSearchResultsForSearchController:(UISearchController*)searchController

这个方法将在搜索栏成为第一响应者或者搜索内容发生变化时调用,其内部实现的主要是搜索规则和显示搜索结果。

获取搜索关键字并根据关键字创建搜索规则,规则是创建了NSPredicate类型的一个变量,关于后面规则的语法可以参考CSDN的这篇博客

    //获取搜索关键字
    NSString* searchString = searchController.searchBar.text;
    //设置搜索规则,此处是字符串包含关键字
    NSPredicate* predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[c] %@", searchString];

记得清除上一次的搜索结果

    //清除旧的搜索结果
    if (self.searchList != nil) {
        [self.searchList removeAllObjects];
    }

然后利用之前创建的搜索规则对tableview中显示的所有数据过滤,把过滤结果添加到searchList中,并让tableview重新加载

    //验证数据,并把通过的数据添加到搜索结果中
    self.searchList = [NSMutableArray arrayWithArray:[_dataList filteredArrayUsingPredicate:predicate]];

    //重新加载tableview
    UITableView* tableView = (id)[self.view viewWithTag:1];
    [tableView reloadData];

这样就完成了最简单的搜索功能,复杂的可以在- (void)updateSearchResultsForSearchController:(UISearchController*)searchController中扩展。

 

完整代码:

  1 //
  2 //  ViewController.m
  3 //  TableView Search
  4 //
  5 //  Created by 张光发 on 15/10/24.
  6 //  Copyright (c) 2015年 张光发. All rights reserved.
  7 //
  8 
  9 #import "ViewController.h"
 10 
 11 @interface ViewController ()
 12 @property (strong, nonatomic) UISearchController* searchController;
 13 @property (strong, nonatomic) NSMutableArray* dataList;
 14 @property (strong, nonatomic) NSMutableArray* searchList;
 15 @end
 16 
 17 @implementation ViewController
 18 
 19 - (void)viewDidLoad
 20 {
 21     [super viewDidLoad];
 22 
 23     self.dataList = [[NSMutableArray alloc] init];
 24     for (int i = 0; i < 100; i++) {
 25         [self.dataList addObject:[NSString stringWithFormat:@"minions %d号🍌", i]];
 26     }
 27     UITableView* tableView = (id)[self.view viewWithTag:1];
 28     UIEdgeInsets tableInset = tableView.contentInset;
 29     tableInset.top = 20;
 30     tableView.contentInset = tableInset;
 31 
 32     UIView* backView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, [[UIApplication sharedApplication] statusBarFrame].size.height)];
 33     backView.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.9];
 34     [self.view addSubview:backView];
 35 
 36     _searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
 37     //显示搜索结果的控制器,必要
 38     _searchController.searchResultsUpdater = self;
 39     //搜索时底层内容是否显示灰色
 40     _searchController.dimsBackgroundDuringPresentation = NO;
 41     //搜索时导航栏是否隐藏
 42     _searchController.hidesNavigationBarDuringPresentation = NO;
 43     //搜索栏的位置、大小信息,必要
 44     _searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, self.searchController.searchBar.frame.origin.y, self.searchController.searchBar.frame.size.width, 44.0);
 45     tableView.tableHeaderView = self.searchController.searchBar;
 46 }
 47 
 48 //TODO: 返回组数
 49 - (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
 50 {
 51     return 1;
 52 }
 53 
 54 //TODO: 返回行数
 55 - (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
 56 {
 57     if (self.searchController.active) {
 58         return [self.searchList count];
 59     }
 60     else {
 61         return [self.dataList count];
 62     }
 63 }
 64 
 65 //TODO: 选择行之后调用
 66 - (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
 67 {
 68     //取消行的选择状态
 69     [tableView deselectRowAtIndexPath:indexPath animated:YES];
 70 }
 71 
 72 //TODO: 返回对应位置的cell
 73 - (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
 74 {
 75     static NSString* flag = @"cellFlag";
 76     UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:flag];
 77     if (cell == nil) {
 78         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:flag];
 79     }
 80     if (self.searchController.active) {
 81         [cell.textLabel setText:self.searchList[indexPath.row]];
 82     }
 83     else {
 84         [cell.textLabel setText:self.dataList[indexPath.row]];
 85     }
 86     return cell;
 87 }
 88 
 89 //TODO: 搜索栏成为第一响应者或者搜索内容发生变化时调用
 90 - (void)updateSearchResultsForSearchController:(UISearchController*)searchController
 91 {
 92     //获取搜索关键字
 93     NSString* searchString = searchController.searchBar.text;
 94     //设置搜索规则,此处是字符串包含关键字
 95     NSPredicate* predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[c] %@", searchString];
 96     //清除旧的搜索结果
 97     if (self.searchList != nil) {
 98         [self.searchList removeAllObjects];
 99     }
100     //验证数据,并把通过的数据添加到搜索结果中
101     self.searchList = [NSMutableArray arrayWithArray:[_dataList filteredArrayUsingPredicate:predicate]];
102 
103     //重新加载tableview
104     UITableView* tableView = (id)[self.view viewWithTag:1];
105     [tableView reloadData];
106 }
107 
108 @end
View Code

 

效果图:

posted @ 2015-10-19 23:05  oooo0oooo0  阅读(632)  评论(0)    收藏  举报