类似于微博、博客这样的应用,通常都需要数据分页。而数据分页常用的做法是在UITableView控件上追加新的数据。从而有效提高用户体验。接下来将介绍其实现过程。
一、实现思路
基本上就是数据源里先只放10条, 点击最后一个cell时, 添加更多的数据到数据源中。
1)取得数据
1
2
3
4
5
6
7
8
9
10
11
|
- ( void )viewDidLoad
{ [super viewDidLoad];
[self _infoNavTabBar];
num=15;
//表格数据
[self loadData];
} |
loadData方法用于拉取API数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
//下载API数据 -( void ) loadData{
NSURL *requestURL=[NSURL URLWithString:[NSString stringWithFormat:@ "http://api.beauty-soft.net/lisvcat.php?a=getUserList&u=username&vkey=lisvcat.php?a=getUserCenterList&u=username&vkey=lisvcat.php?a=getUserCenterList&num=%i&u=ceiba&vkey=%@" ,num,[self
userKey]]];
_ASIHTTPRequest=[[ASIHTTPRequest alloc] initWithURL:requestURL];
_ASIHTTPRequest.delegate=self;
[_ASIHTTPRequest startAsynchronous];
[_ASIHTTPRequest release];
//声明表格
_tableView=[[[UITableView alloc] init] autorelease];
_tableView.frame=self.view.bounds;
_tableView.delegate=self;
_tableView.dataSource=self;
[self.view addSubview:_tableView];
_tableView.frame=CGRectMake(0, 0, [self appWidth], [self appHeight]-90);
} //数据异步下载完成 - ( void )requestFinished:(ASIHTTPRequest *)request{
NSString *_data=[request responseString];
NSMutableDictionary *dir=[_data JSONValue];
dic_=[[NSMutableDictionary alloc] initWithDictionary:[dir objectForKey:@ "data" ]];
[_tableView reloadData];
} |
2)追加“加载更多”单元格记录
1
2
3
4
5
6
7
8
|
//表格单元行数 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { NSArray *rotStr=[dic_ objectForKey:@ "rows" ];
count = [rotStr count];
NSLog(@ "总记录%d" ,count);
return
count+1;
} |
如上述代码所示,记录数量+1的目的就是为了在原有的UITableViewCell上追加一个“加载更多”的Cell。由于API返回的数据是一个层的Dictionary,所以需要使用[dic_objectForKey:@"rows"]代码提取所需要显示的数据行数。
3)为UITableView追加单元格
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
//表格单元格数据 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ NSString *identifier=@ "mycell" ;
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:identifier];
NSInteger row=(indexPath.row)-1;
if
(row<=0) row=0;
UILabel *label = nil;
if
(cell==nil) {
cell =[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
[cell autorelease];
}
if ([indexPath row] == ([rotStr count])) {
//创建loadMoreCell
UITableViewCell *moreCell=[[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@ "mores" ]
autorelease];
UILabel *moreDataLabel=[[UILabel alloc] init];
moreDataLabel.text=@ "查看更多" ;
[moreDataLabel setFont:[UIFont systemFontOfSize:14.0f]];
[moreDataLabel setTextAlignment:NSTextAlignmentCenter];
moreDataLabel.frame=CGRectMake(0, 10, [self screenWidth], 20);
[moreDataLabel setBackgroundColor:[UIColor clearColor]];
[moreCell.contentView addSubview:moreDataLabel];
NSLog(@ "更多..." );
return
moreCell;
}
} |
如上述代码所示,由于在返回表格数据记录时+1,所以在遍历表格数据时需要做相应的处理(即-1),否则将会遍历越界。同时可判断当前的遍历索引是否为数据的总记录,如果是则执行添加“加载更多”的UITableViewCell。当然,一般“加载更多”那个Cell高度是不一样的,所以设置单元格高度时同样也需要做判断处理。如以下代码所示。
1
2
3
4
5
6
7
8
9
10
|
//单元格高度 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if
(indexPath.row==count) {
return
40;
} else {
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
return
cell.frame.size.height;
}
} |
4)处理“加载更多”单元格事件
处理UITableViewCell选择触发事件,是通过didSelectRowAtIndexPath委托方法实现的。同样我们需要在该方法中判读用户所选择的单元格是否为“加载更多”单元格。通过选择索引号即可实现,代码如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//单元格事件 - ( void )tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if
(indexPath.row == count) {
//”加载更多“单元格事件
[self performSelectorInBackground:@selector(loadMore) withObject:nil];
//[loadMoreCell setHighlighted:NO];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
return ;
}
//其他单元格事件
} |
5)追加数据
用户点击”加载更多“单元格后,将触发loadMore方法,在该方法中实现分页数据的拉取。为了提高效率,所以这里使用了performSelectorInBackground方法创建后台了线程。loadMore方法代码如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
//1、点击加载更多数据 -( void )loadMore
{ page++;
if
(page<=3) {
page=3;
}
//在子线各中处理同步请求
[self performSelectorOnMainThread:@selector(SynchronousData:) withObject:nil waitUntilDone:NO];
} //2、请求数据 -( void ) SynchronousData:(NSMutableDictionary *)data
{ //加载你的数据
NSURL *url=[NSURL URLWithString:[NSString stringWithFormat:@ "http://api.beauty-soft.net/lisvcat.php?a=getUserList&u=username&vkey=lisvcat.php?a=getUserCenterList&u=username&vkey=lisvcat.php?a=getUserCenterList&num=5&u=ceiba&vkey=%@&p=%i" ,[self
userKey],page]];
NSLog(@ "n请求的URL:%@n" ,url);
ASIHTTPRequest *request = [ ASIHTTPRequest requestWithURL :url];
// 开始同步请求
[request startSynchronous];
NSError *error = [request error ];
assert
(!error);
NSString *requestStr=[request responseString];
NSMutableDictionary *dir=[requestStr JSONValue];
NSMutableDictionary *str=[dir objectForKey:@ "data" ];
NSMutableArray *rotStr=[str objectForKey:@ "rows" ];
[self performSelectorOnMainThread:@selector(appendTableWith:) withObject:rotStr waitUntilDone:NO];
} //3、根据请求的数据动态添加单元 -( void ) appendTableWith:(NSMutableArray *)data
{ for
( int
i=0;i<[data count];i++) {
[[dic_ objectForKey:@ "rows" ] addObject:[data objectAtIndex:i]];
//[data_ addObject:[data objectAtIndex:i]];
}
NSMutableArray *insertIndexPaths = [NSMutableArray arrayWithCapacity:10];
for
( int
ind = 0; ind < [data count]; ind++) {
NSIndexPath *newPath = [NSIndexPath indexPathForRow:[[dic_ objectForKey:@ "rows" ]
indexOfObject:[data objectAtIndex:ind]] inSection:0];
[insertIndexPaths addObject:newPath];
}
[self.tableView insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationFade];
} |
如上述代码所示,共分为3个步骤。首先由loadMore方法初始化请求变量,例如修改请求链接的分页码等;然后在SynchronousData方法中同步获取API接口中的数据;最后在appendTableWith方法中完成UITableViewCell单元格的动态添加。