今天尝试了下IOS中的下拉刷新,遇到各种各样的问题,写一篇日志做一个总结。
一、下拉刷新的实现
EGORefreshTableHeaderView
下载地址为:https://github.com/enormego/EGOTableViewPullRefresh
和大部分第三方库一样,zip展开后其中带有一个demo和一个库文件夹,如果要详细了解,建议先看看demo。其实这个第三方的用法也相当简单:
1. 将第三方库中的库文件夹拖到XCode中,并且选择拷贝。由于EGOTableViewPullRefresh依赖于IOS的QuartzCore.frameworks,所以别忘了加上。
EGORefreshTableHeaderView.h
3. 在头文件中加入以下代码,其中reloadTableViewDataSource是在下拉松开后,会调用的代码,而doneLoadingTableViewData是刷新成功之后调用的代码,主要用于隐藏table上面的下拉区域。
[cpp]
1. {
2. EGORefreshTableHeaderView *_refreshHeaderView;
3. BOOL _reloading;
4. }
5.
6. -(void)reloadTableViewDataSource;
7. -(void)doneLoadingTableViewData;
4. 在m文件中初始化下拉刷新:
[cpp]
1. //初始化下拉刷新
2. if(_refreshHeaderView ==nil){
3.
4. EGORefreshTableHeaderView *view =[[EGORefreshTableHeaderView alloc] initWithFrame:CGRectMake(0.0f, 0.0f - self.tableView.bounds.size.height, self.view.frame.size.width, self.tableView.bounds.size.height)];
5. view.delegate = self;
6. [self.tableView addSubview:view];
7. _refreshHeaderView = view;
8. }
9.
10. // update the last update date
11. [_refreshHeaderView refreshLastUpdatedDate];
5. 在m文件中实现以下方法:
[cpp]
1. #pragma mark Data Source Loading / Reloading Methods
2.
3. -(void)reloadTableViewDataSource{
4.
5. // should be calling your tableviews data source model to reload
6. // put here just for demo
7. _reloading =YES;
8. }
9.
10. -(void)doneLoadingTableViewData{
11.
12. // model should call this when its done loading
13. _reloading =NO;
14. [_refreshHeaderView egoRefreshScrollViewDataSourceDidFinishedLoading:self.tableView];
15. }
16.
17. #pragma mark -
18. #pragma mark UIScrollViewDelegate Methods
19.
20. -(void)scrollViewDidScroll:(UIScrollView *)scrollView{
21.
22. [_refreshHeaderView egoRefreshScrollViewDidScroll:scrollView];
23.
24. }
25.
26. -(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
27.
28. [_refreshHeaderView egoRefreshScrollViewDidEndDragging:scrollView];
29.
30. }
31.
32. #pragma mark -
33. #pragma mark EGORefreshTableHeaderDelegate Methods
34.
35. -(void)egoRefreshTableHeaderDidTriggerRefresh:(EGORefreshTableHeaderView*)view{
36.
37. [self reloadTableViewDataSource];
38. [self performSelector:@selector(doneLoadingTableViewData) withObject:nil afterDelay:3.0];
39.
40. }
41.
42. -(BOOL)egoRefreshTableHeaderDataSourceIsLoading:(EGORefreshTableHeaderView*)view{
43.
44. return _reloading; // should return if data source model is reloading
45.
46. }
47.
48. -(NSDate*)egoRefreshTableHeaderDataSourceLastUpdated:(EGORefreshTableHeaderView*)view{
49.
50. return [NSDate date]; // should return date data source was last changed
(doneLoadingTableViewData可以连续多次调用,但是效果只有一次)
此时你已经可以运行代码,会发现,已经成功地添加了一个下拉功能,当然,具体如何刷新,那是需要自己去维护。
二、下拉刷新失败的问题
第一个可能失败的问题是,主线程与非主线程中刷新UI。一般来说IOS是不支持在非主线程中刷新UI的,会造成各种各样的问题导致程序崩溃。因此,如果下拉刷新是一个耗时操作,又是先分线程中进行的(比如发送HTTP Request向服务器发送请求获取数据,在数据成功返回后刷新UI),那么就需要将刷新过程放入一个函数,在分线程中调用
[selfperformSelectorOnMainThread:@selector(refreshTable)withObject:nilwaitUntilDone:NO];告诉主线程如何刷新UI。其中,refreshTable为刷新函数。
第二个问题,纠结了好久是有关自定义TableViewController中的cell刷新。用IB定义了cell的外观,并且为cell中的所有view都用tag标记。需要采用来刷新:
[cpp]
1. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
2. {
3. static NSString *CellIdentifier = @"PrivateMessageCell";
4. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
5.
6. // Configure the cell...
7. PrivateMessageListItem *item = (PrivateMessageListItem *)[privateMessageList objectAtIndex:indexPath.row];
8.
9. //用户头像
10. UIImageView *objectProfileImage = (UIImageView *)[cell viewWithTag:1000];
11. [objectProfileImage setImageWithURL:[NSURL URLWithString: item.contacter_info.pic]];
12.
13.
14. return cell;
15. }
其中千万别采用[self.view viewWithTag: 1000]来获取元素。这种方法能成功load数据,但是第二次刷新的时候就不会成功。