使用 UITableView 创建表格应用演练(3)——使用区段分类显示表格数据

上一篇 使用 UITableView 创建表格应用演练(2)——从plist文件加载并显示数据" 完成后,“微博关注人”这个应用虽然距离最终的完成还有不小的距离,但从视觉上已经比演练(1)完成时有了不小的改进。:]

细心的朋友们在上次演练中已经发现,我们定义的数据结构中,有一个名为“类别”的字段,这个字段的设置主要用于帮助我们更好地管理我们的关注对象。本文演练仅仅涉及一个问题,就是如何按照“类别”在表格中分区段显示数据。本此演练之后,相信您会对iOS中的数组(NSMutableArray)和plist文件的使用也会有一个新的理解。

一. 开始之前

开始之前,我们需要简单回顾一下上一次的一些内容,这样便于我们演练的开始。

1. 在FocusUsers.plist文件中顺序存放所有关注用户的数据;

2. 我们定义了一个名为JOYFocusUser的类来存放每个用户的信息;

3. 我们在视图控制器中用到了一个NSMutableArray数组存放plist文件内容,并通过JOYFocusUser类做为映射,便于程序编写过程中的访问。

那么现在问题出来了——从plist文件中加载过来的数据是一个序列的,而分区段显示数据时,单一序列的数组显然有些难以胜任,这个时候我们需要做一个中转。如下图所示:

如果我们从上一讲中的单一序列,变成有图所示的二维序列问题似乎就好解决了。:]

好,思路有了,现在让我们马上动手。

二. 数据调整

1. 在导航区域,点击“FocusUsers.plist”文件,打开我们上次演练中建立的plist文件;

2. 在“FocusUsers.plist”上点击鼠标右键,选择“Open As”“Source Code”,并使用下列代码替换我们上次使用的plist内容:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 3 <plist version="1.0">
 4     <array>
 5         <array>
 6             <dict>
 7                 <key>UserName</key>
 8                 <string>爱Apps</string>
 9                 <key>Image</key>
10                 <string>爱Apps.jpeg</string>
11                 <key>WebSite</key>
12                 <string>http://weibo.com/iapps</string>
13                 <key>Favorite</key>
14                 <real>3.5</real>
15                 <key>Category</key>
16                 <string>苹果咨询</string>
17             </dict>
18             <dict>
19                 <key>UserName</key>
20                 <string>苹果汇</string>
21                 <key>Image</key>
22                 <string>苹果汇.jpeg</string>
23                 <key>WebSite</key>
24                 <string>http://weibo.com/appleus</string>
25                 <key>Favorite</key>
26                 <real>3.5</real>
27                 <key>Category</key>
28                 <string>苹果咨询</string>
29             </dict>
30             <dict>
31                 <key>UserName</key>
32                 <string>数码iPhone大百科</string>
33                 <key>Image</key>
34                 <string>数码iPhone大百科.jpeg</string>
35                 <key>WebSite</key>
36                 <string>http://weibo.com/gx110</string>
37                 <key>Favorite</key>
38                 <real>3.5</real>
39                 <key>Category</key>
40                 <string>苹果咨询</string>
41             </dict>
42         </array>
43         <array>
44             <dict>
45                 <key>UserName</key>
46                 <string>新浪视野</string>
47                 <key>Image</key>
48                 <string>新浪视野.jpeg</string>
49                 <key>WebSite</key>
50                 <string>http://weibo.com/wboard</string>
51                 <key>Favorite</key>
52                 <real>3.5</real>
53                 <key>Category</key>
54                 <string>官方机构</string>
55             </dict>
56         </array>
57         <array>
58             <dict>
59                 <key>UserName</key>
60                 <string>李开复</string>
61                 <key>Image</key>
62                 <string>李开复.jpeg</string>
63                 <key>WebSite</key>
64                 <string>http://weibo.com/kaifulee</string>
65                 <key>Favorite</key>
66                 <real>3.5</real>
67                 <key>Category</key>
68                 <string>IT名人</string>
69             </dict>
70         </array>
71     </array>
72 </plist>

对比上一次演练中我们使用的plist文件,我们多引入了一层array定义,这样就把原有的一维数据序列,调整成二维序列了。怎么样?还不错吧。:]

三. 数据加载处理

1. 在导航区域,点击打开“JOYTableViewController.m”文件;

2. 在接口定义中将原来定义的数据名称由_userList改为_categoryList,如下所示:

1 @interface JOYTableViewController () {
2 @private
3     NSMutableArray *_categoryList;
4 }

3. 在viewDidLoad方法中调整数据加载部分进行调整,调整后的viewDidLoad方法如下所示:

 1 - (void)viewDidLoad
 2 {
 3     [super viewDidLoad];
 4 
 5     // 设定pList文件路径
 6     NSString *dataPath = [[NSBundle mainBundle]pathForResource:@"FocusUsers.plist" ofType:nil];
 7     // 填充数组内容
 8     NSMutableArray *array = [NSMutableArray arrayWithContentsOfFile:dataPath];
 9 
10     _categoryList = [[NSMutableArray alloc]init];
11     for (NSDictionary *item in array) {
12         NSMutableArray *userList = [[NSMutableArray alloc]init];
13         
14         // 针对每个分类项,创建一个用户数组
15         for (NSDictionary *users in item) {
16             JOYFocusUser *user = [[JOYFocusUser alloc]initWithItem:users];
17             [userList addObject:user];
18         }
19         
20         // 将用户数组项目添加到分类数组中
21         [_categoryList addObject:userList];
22     }
23 }

4. 找到numberOfSectionsInTableView方法,将其中代码进行修改,如下所示:

1 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
2 {
3     return [_categoryList count];
4 }

在本演练数据中,我们一共包含三个分类,所以在此返回结果是3。

5. 找到

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

方法,将其中代码进行修改,如下所示:

1 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
2 {
3     return [[_categoryList objectAtIndex:section]count];
4 }

这里的代码稍微有些别扭,我们会在后续调整一下,让它更好读一些,在此先简单解释一下。

从plist文件的结构中,我们不难发现[_categoryList objectAtIndex:section]对应的是指定区段数的一个用户数组,假如我们把这个理解为“userList”,则这条语句可以看成是return [userList count],返回的是指定区段的用户数组的个数。

6. 找到

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

方法,将其中解析数据部分代码进行修改,修改后的方法如下所示:

 1 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 2 {
 3     static NSString *CellIdentifier = @"Cell";
 4     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
 5     
 6     // Configure the cell...
 7     // 实例化单元格对象
 8     if (cell == nil) {
 9         cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
10     }
11     
12     NSMutableArray *array = [_categoryList objectAtIndex:[indexPath section]];
13     JOYFocusUser *user = [array objectAtIndex:[indexPath row]];
14     
15     // 设置单元格文本
16 //    NSDictionary *item = [_userList objectAtIndex:indexPath.row];
17     [cell.textLabel setText:[user userName]];
18     // 设定字体
19     [cell.textLabel setFont:[UIFont fontWithName:@"Helvetica" size:16.0f]];
20     // 改变字体颜色
21     [cell.textLabel setTextColor:[UIColor orangeColor]];
22     // 调整文本居中对齐
23     [cell.textLabel setTextAlignment:UITextAlignmentCenter];
24     
25     // 显示头像
26     [cell.imageView setImage:[user image]];
27     
28     return cell;
29 }

为了便于大家的阅读,我把上一次演练中的代码注释了,这样方便我们更加直观地看出到底做了哪些修改。

7. 运行一下,看看效果:]

天啊,忙乎了一溜够,竟然和上次演练之后没有发生任何的变化,这⋯⋯

不要着急,现在激动人心的时刻就要到了,嘿嘿。

8. 找到numberOfSectionsInTableView方法,在它的下面插入一个

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section 方法

并增加一条语句,如下所示:

1 - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
2     // 获取指定区段的用户数组
3     NSMutableArray *userList = [_categoryList objectAtIndex:section];
4     // 获取数组中第一个用户记录
5     JOYFocusUser *user = [userList objectAtIndex:0];
6     // 返回该用户的分类名称
7     return user.categoryName;
8 }

相关语句到底干了什么,见注释即可,我就不再啰嗦了。

9. 运行一下,如下图所示:

哈哈,怎么样?不复杂吧。

小提示:可能有不少从其他平台,例如Eclipse或者MS VS等转过来的朋友会向我当初一样有一些类似的疑问:这个方法是怎么加入的呢?我怎么知道系统预设了这个方法呢?有没有某个菜单命令能够弹出一个对话框,让我选择具体要重载哪个方法呢?

答案是直接输入。呵呵,刚开始使用Xcode时,我也有些不习惯,不过后来发现,Xcode提供的智能输入提示非常友好,在程序开发时非常高效地,程序员不用时不时地因为一些小事,就不得不把手从键盘移到鼠标上,去做一些无聊的事情。在Xcode中,编写某一个类的代码时,几乎可以不用使用鼠标,就完成所有的编码工作。

好了,言归正传,在上述的代码中,某些地方有些取巧,如果你只是开发这么一个简单的应用,已经足够了。不过如果考虑到以后系统的维护和扩充,我们还是要尽量将数据和界面分开。

四. 使用分类数据模型

1. 在导航区域,点击并打开“JOYFocusUser.h”文件,在文件末尾增加如下代码:

1 @interface JOYCategory : NSObject
2 
3 @property (strong, nonatomic) NSString *categoryName;
4 @property (strong, nonatomic) NSMutableArray *userList;
5 
6 // 使用用户列表实例化对象
7 - (id)initWithArray:(NSMutableArray *)userList;
8 
9 @end

在此,我们新定义了一个JOYCategory的类,用于按类别存储用户列表;

2. 点击打开“JOYFocusUser.m”文件,在文件的末尾增加如下代码:

 1 @implementation JOYCategory
 2 @synthesize categoryName = _categoryName;
 3 @synthesize userList = _userList;
 4 
 5 - (id)initWithArray:(NSMutableArray *)userList {
 6     
 7     self = [super init];
 8     if (self) {
 9         NSMutableArray *list = [[NSMutableArray alloc]init];
10         for (NSDictionary *item in userList) {
11             JOYFocusUser *user = [[JOYFocusUser alloc]initWithItem:item];
12             [list addObject:user];
13         }
14         
15         JOYFocusUser *user = [list objectAtIndex:0];
16         _categoryName = user.categoryName;
17         _userList = list;
18     }
19     return self;
20 }
21 
22 @end

3. 在导航区域,点击打开“JOYTableViewController.m”文件;

4. 对viewDidLoad中的数据加载部分的代码调整如下:

 1 - (void)viewDidLoad
 2 {
 3     [super viewDidLoad];
 4 
 5     // 设定pList文件路径
 6     NSString *dataPath = [[NSBundle mainBundle]pathForResource:@"FocusUsers.plist" ofType:nil];
 7     // 填充数组内容
 8     NSMutableArray *array = [NSMutableArray arrayWithContentsOfFile:dataPath];
 9 
10     _categoryList = [[NSMutableArray alloc]init];
11 //    for (NSDictionary *item in array) {
12 //        NSMutableArray *userList = [[NSMutableArray alloc]init];
13 //        
14 //        // 针对每个分类项,创建一个用户数组
15 //        for (NSDictionary *users in item) {
16 //            JOYFocusUser *user = [[JOYFocusUser alloc]initWithItem:users];
17 //            [userList addObject:user];
18 //        }
19 //        
20 //        // 将用户数组项目添加到分类数组中
21 //        [_categoryList addObject:userList];
22 //    }
23     for (NSMutableArray *item in array) {
24         JOYCategory *category = [[JOYCategory alloc]initWithArray:item];
25         [_categoryList addObject:category];
26     }
27 }

5. 在 

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section方法中做如下调整:

 1 - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
 2 //    // 获取指定区段的用户数组
 3 //    NSMutableArray *userList = [_categoryList objectAtIndex:section];
 4 //    // 获取数组中第一个用户记录
 5 //    JOYFocusUser *user = [userList objectAtIndex:0];
 6 //    // 返回该用户的分类名称
 7 //    return user.categoryName;
 8     JOYCategory *category = [_categoryList objectAtIndex:section];
 9     return [category categoryName];
10 }

6. 在

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section方法中做如下调整:

1 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
2 {
3 //    return [[_categoryList objectAtIndex:section]count];
4     JOYCategory *category = [_categoryList objectAtIndex:section];
5     return [category.userList count];
6 }

7. 在

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath方法中做如下调整:

 1 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 2 {
 3     static NSString *CellIdentifier = @"Cell";
 4     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
 5     
 6     // Configure the cell...
 7     // 实例化单元格对象
 8     if (cell == nil) {
 9         cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
10     }
11     
12 //    NSMutableArray *array = [_categoryList objectAtIndex:[indexPath section]];
13 //    JOYFocusUser *user = [array objectAtIndex:[indexPath row]];
14     JOYCategory *category = [_categoryList objectAtIndex:[indexPath section]];
15     JOYFocusUser *user = [category.userList objectAtIndex:[indexPath row]];
16     
17     // 设置单元格文本
18 //    NSDictionary *item = [_userList objectAtIndex:indexPath.row];
19     [cell.textLabel setText:[user userName]];
20     // 设定字体
21     [cell.textLabel setFont:[UIFont fontWithName:@"Helvetica" size:16.0f]];
22     // 改变字体颜色
23     [cell.textLabel setTextColor:[UIColor orangeColor]];
24     // 调整文本居中对齐
25     [cell.textLabel setTextAlignment:UITextAlignmentCenter];
26     
27     // 显示头像
28     [cell.imageView setImage:[user image]];
29     
30     return cell;
31 }

小提示:为了便于大家的阅读,我把前面演练中的代码注释了,这样方便我们更加直观地看出到底做了哪些修改。由于我把每一个方法的完成代码都复制过来了,其实我们在每个方法中所作的修改只是一两条语句而已。

8. 运行看一下效果,和前面演练完的效果并没有太大的变化,不过现在的代码的可读性已经有所提高了:]

五. 小结

首先要向大家表示歉意,因为本人的博客只是利用业余时间编写的,更新速度有些缓慢,还望大家见谅。

本演练源程序下载地址:JoyiOSMyFocus3.zip

到目前位置,我们对UITableView的数据加载、显示、分组已经做了一个初步的介绍。在后面的演练中,我们将针对自定义单元格、表格数据操作以及自定义视图进行介绍,同时引入一个iOS应用中非常常见的Navigation控件。计划还需要两~三章的内容可以完成,敬请期待。

posted @ 2012-06-10 11:21  趣味苹果开发  阅读(4668)  评论(13编辑  收藏  举报