开春大礼《华为云技术精选集》大厂100+前沿技术实战分享!>>>
上一篇 使用 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控件。计划还需要两~三章的内容可以完成,敬请期待。
原文链接:
http://www.cnblogs.com/liufan9/archive/2012/06/10/2542153.html