EGORefreshTableHeaderView 解读

来源:互联网 发布:前田阳菜 pk 樱井知香 编辑:程序博客网 时间:2024/05/23 01:56

查看源码。称它为ELTableViewController是取了EGORefreshTableHeaderView以及LoadMoreTableFooterView的首字母。

这份代码中包含了一个示例程序以及三个必备组件:

1、  EGORefreshTableHeaderView

2、  LoadMoreTableFooterView(修改版,原版不能适应任何尺寸的高度)

3、  Apple官方提供的异步下载UITableView中的图片的示例组件(IconDownLoader),这个只适用于下载类似于社交网络中的用户头像,不建议使用它来下载那些大图片,因为它甚至都没有缓存(如果图片很大,推荐使用SDImage)


代码解读

它已经内置实现了这些协议,所以在你使用它的时候,无需设置和实现。

[cpp] view plain copy
 print?
  1. @interface ELTableViewController : UIViewController  
  2. <  
  3. UITableViewDelegate,  
  4. UITableViewDataSource,  
  5. EGORefreshTableHeaderDelegate,  
  6. LoadMoreTableFooterDelegate,  
  7. IconDownloaderDelegate  
  8. >  

对于不断变化的业务逻辑,这里提供了所有需要实现的block:

[cpp] view plain copy
 print?
  1. //blocks for UITableView delegate  
  2. typedef UITableViewCell* (^cellForRowAtIndexPathDelegate) (UITableView *,NSIndexPath *);  
  3. typedef CGFloat (^heightForRowAtIndexPathDelegate) (UITableView *,NSIndexPath *);  
  4. typedef void (^didSelectRowAtIndexPathDelegate) (UITableView *,NSIndexPath *);  
  5.   
  6. //blocks for refresh and load more  
  7. typedef void (^refreshDataSourceFunc) (void);  
  8. typedef void (^loadMoreDataSourceFunc) (void);  
  9.   
  10. typedef void (^refreshDataSourceCompleted) (void);  
  11. typedef void (^loadMoreDataSourceCompleted) (void);  
  12. //use to load image (async)  
  13. typedef void (^loadImagesForVisiableRowsFunc) (void);  
  14. typedef void (^appImageDownloadCompleted) (NSIndexPath *);  


它们以属性的形式对外公开:

[cpp] view plain copy
 print?
  1. //property for blocks  
  2. @property (nonatomic,copy) cellForRowAtIndexPathDelegate cellForRowAtIndexPathDelegate;  
  3. @property (nonatomic,copy) heightForRowAtIndexPathDelegate heightForRowAtIndexPathDelegate;  
  4. @property (nonatomic,copy) didSelectRowAtIndexPathDelegate didSelectRowAtIndexPathDelegate;  
  5.   
  6. @property (nonatomic,copy) loadMoreDataSourceFunc loadMoreDataSourceFunc;  
  7. @property (nonatomic,copy) refreshDataSourceFunc refreshDataSourceFunc;  
  8. @property (nonatomic,copy) refreshDataSourceCompleted refreshDataSourceCompleted;  
  9. @property (nonatomic,copy) loadMoreDataSourceCompleted loadMoreDataSourceCompleted;  
  10.   
  11. @property (nonatomic,copy) loadImagesForVisiableRowsFunc loadImagesForVisiableRowsFunc;  
  12. @property (nonatomic,copy) appImageDownloadCompleted appImageDownloadCompleted;  

对于上提加载更多、下拉刷新、图片异步加载这几个功能都是可选的,它们以组件的形式存在。比如,在实例化该controller的时候你就可以设置上提和下拉是否可用。而对于图片下载,你只要不实现其相应得block,它也不会对你造成额外的负担。

[cpp] view plain copy
 print?
  1. - (id)initWithRefreshHeaderViewEnabled:(BOOL)enableRefreshHeaderView   
  2. andLoadMoreFooterViewEnabled:(BOOL)enableLoadMoreFooterView;  
  3.   
  4. - (id)initWithRefreshHeaderViewEnabled:(BOOL)enableRefreshHeaderView   
  5.           andLoadMoreFooterViewEnabled:(BOOL)enableLoadMoreFooterView   
  6.                      andTableViewFrame:(CGRect)frame;  

[cpp] view plain copy
 print?
  1. #pragma mark - UITableView Delegate -  
  2. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{  
  3.     if (nil==self.dataSource) {  
  4.         return 0;  
  5.     }  
  6.       
  7.     return [self.dataSource count];  
  8. }  
  9.   
  10. - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{  
  11.     if (!self.cellForRowAtIndexPathDelegate) {  
  12.         @throw [NSException exceptionWithName:@"Framework Error"   
  13.                                        reason:@"Must be setting cellForRowAtIndexPathBlock for UITableView" userInfo:nil];  
  14.     }  
  15.     return self.cellForRowAtIndexPathDelegate(tableView,indexPath);  
  16. }  
  17.   
  18. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{  
  19.     if (!self.heightForRowAtIndexPathDelegate) {  
  20.         @throw [NSException exceptionWithName:@"Framework Error"   
  21.                                        reason:@"Must be setting heightForRowAtIndexPathDelegate for UITableView" userInfo:nil];  
  22.     }  
  23.     return self.heightForRowAtIndexPathDelegate(tableView,indexPath);  
  24. }  
  25.   
  26. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{  
  27.     if (self.didSelectRowAtIndexPathDelegate) {  
  28.         self.didSelectRowAtIndexPathDelegate(tableView,indexPath);  
  29.     }  
  30. }  
  31.   
  32. #pragma mark - LoadMoreTableFooterDelegate Methods -  
  33. - (void)loadMoreTableFooterDidTriggerRefresh:(LoadMoreTableFooterView *)view{  
  34.     if (self.loadMoreDataSourceFunc&&self.loadMoreDataSourceCompleted) {  
  35.         self.loadMoreDataSourceFunc();  
  36.           
  37.         double delayInSeconds = 3.0;  
  38.         dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);  
  39.         dispatch_after(popTime, dispatch_get_main_queue(),   
  40.                        self.loadMoreDataSourceCompleted);  
  41.     }  
  42. }  
  43.   
  44. - (BOOL)loadMoreTableFooterDataSourceIsLoading:(LoadMoreTableFooterView *)view{  
  45.     return self.isLoadingMore;  
  46. }  
  47.   
  48. #pragma mark - EGORefreshTableHeaderDelegate Methods -  
  49. -(void)egoRefreshTableHeaderDidTriggerRefresh:(EGORefreshTableHeaderView *)view{  
  50.     if (self.refreshDataSourceFunc&&self.refreshDataSourceCompleted){  
  51.         self.refreshDataSourceFunc();  
  52.           
  53.         double delayInSeconds = 3.0;  
  54.         dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);  
  55.         dispatch_after(popTime, dispatch_get_main_queue(),   
  56.                        self.refreshDataSourceCompleted);  
  57.     }  
  58. }  
  59.   
  60. -(BOOL)egoRefreshTableHeaderDataSourceIsLoading:(EGORefreshTableHeaderView *)view{  
  61.     return self.isRefreshing;  
  62. }  
  63.   
  64. -(NSDate *)egoRefreshTableHeaderDataSourceLastUpdated:(EGORefreshTableHeaderView *)view{  
  65.     return [NSDate date];  
  66. }  
  67.   
  68. #pragma mark - UIScrollViewDelegate Methods -  
  69. -(void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView{  
  70.     self.currentOffsetPoint=scrollView.contentOffset;  
  71. }  
  72.   
  73. -(void)scrollViewDidScroll:(UIScrollView *)scrollView{  
  74.     CGPoint pt=scrollView.contentOffset;  
  75.     if (self.currentOffsetPoint.y<pt.y) {  
  76.         [self.loadMoreFooterView loadMoreScrollViewDidScroll:scrollView];  
  77.     }else {       
  78.         [self.refreshHeaderView egoRefreshScrollViewDidScroll:scrollView];  
  79.     }  
  80. }  
  81.   
  82. -(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{  
  83.     CGPoint pt=scrollView.contentOffset;  
  84.     if (self.currentOffsetPoint.y<pt.y) {  
  85.         [self.loadMoreFooterView loadMoreScrollViewDidEndDragging:scrollView];  
  86.     }else {  
  87.         [self.refreshHeaderView egoRefreshScrollViewDidEndDragging:scrollView];  
  88.     }  
  89.       
  90.     if (!decelerate&&self.loadImagesForVisiableRowsFunc) {  
  91.         self.loadImagesForVisiableRowsFunc();  
  92.     }  
  93. }  
  94.   
  95. -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{  
  96.     if (self.loadImagesForVisiableRowsFunc) {  
  97.         self.loadImagesForVisiableRowsFunc();  
  98.     }  
  99. }  
  100.   
  101. #pragma mark - download image async -  
  102. -(void)appImageDidLoad:(NSIndexPath *)indexPath{  
  103.     if (self.appImageDownloadCompleted) {  
  104.         self.appImageDownloadCompleted(indexPath);  
  105.     }  
  106. }  

ELTableViewController 的使用

创建一个新的controller继承自:ELTableViewController;

override父类的initBlocks方法:

[cpp] view plain copy
 print?
  1. #pragma mark - private methods -  
  2. - (void)loadDataSource{  
  3.     self.dataSource=[NSMutableArray array];  
  4.     [self.dataSource addObject:@"dataSource_1"];  
  5.     [self.dataSource addObject:@"dataSource_2"];  
  6.     [self.dataSource addObject:@"dataSource_3"];  
  7.     [self.dataSource addObject:@"dataSource_4"];  
  8.     [self.dataSource addObject:@"dataSource_5"];  
  9.     [self.dataSource addObject:@"dataSource_6"];  
  10.     [self.dataSource addObject:@"dataSource_7"];  
  11.     [self.dataSource addObject:@"dataSource_8"];  
  12.     [self.dataSource addObject:@"dataSource_9"];  
  13.     [self.dataSource addObject:@"dataSource_10"];  
  14. }  
  15.   
  16. - (void)initBlocks{  
  17.     __block TestViewController *blockedSelf=self;  
  18.       
  19.     //load more  
  20.     self.loadMoreDataSourceFunc=^{  
  21.         [blockedSelf.dataSource addObject:@"loadMoreDataSourceBlock_1"];  
  22.         [blockedSelf.dataSource addObject:@"loadMoreDataSourceBlock_2"];  
  23.         [blockedSelf.dataSource addObject:@"loadMoreDataSourceBlock_3"];  
  24.         [blockedSelf.dataSource addObject:@"loadMoreDataSourceBlock_4"];  
  25.         [blockedSelf.dataSource addObject:@"loadMoreDataSourceBlock_5"];  
  26.           
  27.         blockedSelf.isLoadingMore=YES;  
  28.         [self.tableView reloadData];  
  29.           
  30.         NSLog(@"loadMoreDataSourceBlock was invoked");  
  31.     };  
  32.       
  33.     //load more completed  
  34.     self.loadMoreDataSourceCompleted=^{  
  35.         blockedSelf.isLoadingMore=NO;  
  36.         [blockedSelf.loadMoreFooterView loadMoreScrollViewDataSourceDidFinishedLoading:self.tableView];  
  37.           
  38.         NSLog(@"after loadMore completed");  
  39.     };  
  40.       
  41.     //refresh  
  42.     self.refreshDataSourceFunc=^{  
  43.         blockedSelf.dataSource=[NSMutableArray array];  
  44.         [blockedSelf.dataSource addObject:@"refreshDataSourceBlock_1"];  
  45.         [blockedSelf.dataSource addObject:@"refreshDataSourceBlock_2"];  
  46.         [blockedSelf.dataSource addObject:@"refreshDataSourceBlock_3"];  
  47.         [blockedSelf.dataSource addObject:@"refreshDataSourceBlock_4"];  
  48.         [blockedSelf.dataSource addObject:@"refreshDataSourceBlock_5"];  
  49.           
  50.         blockedSelf.isRefreshing=YES;  
  51.         [self.tableView reloadData];  
  52.           
  53.         NSLog(@"refreshDataSourceBlock was invoked");  
  54.     };  
  55.       
  56.     //refresh completed  
  57.     self.refreshDataSourceCompleted=^{  
  58.         blockedSelf.isRefreshing=NO;  
  59.         [blockedSelf.loadMoreFooterView loadMoreScrollViewDataSourceDidFinishedLoading:self.tableView];  
  60.           
  61.         NSLog(@"after refresh completed");  
  62.     };  
  63.       
  64.     self.cellForRowAtIndexPathDelegate=^(UITableView *tableView, NSIndexPath *indexPath){  
  65.         static NSString *cellIdentifier=@"cellIdentifier";  
  66.         UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier];  
  67.         if (!cell) {  
  68.             cell=[[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]autorelease];  
  69.         }  
  70.           
  71.         cell.textLabel.text=[blockedSelf.dataSource objectAtIndex:indexPath.row];  
  72.           
  73.         NSLog(@"block:cellForRowAtIndexPathBlock has been invoked.");  
  74.           
  75.         return cell;  
  76.     };  
  77.       
  78.     self.heightForRowAtIndexPathDelegate=^(UITableView *tableView, NSIndexPath *indexPath){  
  79.         NSLog(@"block:heightForRowAtIndexPathBlock has been invoked.");  
  80.         return 60.0f;  
  81.     };  
  82.       
  83.     self.didSelectRowAtIndexPathDelegate=^(UITableView *tableView, NSIndexPath *indexPath){  
  84.         NSLog(@"block:didSelectRowAtIndexPathDelegate has been invoked.");  
  85.     };  
  86.       
  87. }  

然后在ViewDidLoad中调用:

[cpp] view plain copy
 print?
  1. [self initBlocks];  
  2.     [self loadDataSource];  
  3.     [self.tableView reloadData];  

最后,你在实例化该controller的时候,可以指定是否使用上提和下拉

[cpp] view plain copy
 print?
  1. self.viewController = [[[TestViewController alloc] initWithRefreshHeaderViewEnabled:YES andLoadMoreFooterViewEnabled:YES]autorelease];  

写在最后

写完之后,我用它重构了一下快易博中,新浪微博的几个视图。也省掉了一些冗余代码,如果当初在开发的时候就使用它的话,感觉还是省了一些功夫的。

它其实也还是比较简单的封装,所以还不是很具有业务相关性,同时也可见它还有很多可继续增强的功能:

1、  封装增删改查功能

2、  封装加载、操作时动画

3、  封装网络加载的统一实现

……………….

先写到这里吧。


推荐两篇讲ios block非常不错的文章:

http://lldong.github.com/blog/2011/12/30/blocks/

http://yannickloriot.com/2011/11/working-with-blocks/


源码地址:

https://github.com/yanghua/ELTableViewController

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 第二类童子命该怎么办 一楼潮湿有虫子怎么办 镜子对着卧室门怎么办 入户门对着墙角怎么办 别人睡了主卧室怎么办 主卧别人睡过了怎么办 卧室门对着过道怎么办 有墙角对着窗户怎么办 卧室门对着墙角怎么办 冰箱和大门对着怎么办 冰箱对着入户门怎么办 哪来的大路对门怎么办 卧室窗户对着路怎么办 床尾对着窗户怎么办 床头对着厕所门怎么办 5楼阳台对着马路怎么办 宿舍门对着楼梯怎么办 如果镜子对着门怎么办 厕所门对着厨房怎么办 客厅门对着大门怎么办 床头对着厕所墙怎么办 被小狗舔了伤口怎么办 狗狗伤口好不了怎么办 狗的伤口发炎了怎么办 大门正对房门该怎么办 房门正对厕所门怎么办 浴室镜子对着门怎么办 房间门正对厕所怎么办 厕所斜对着大门怎么办 刚开麻将馆没人怎么办 入户门正对电梯怎么办 电梯对着入户门怎么办 电梯门对着房门怎么办 厨房门对入户门怎么办 餐桌对着入户门怎么办 房门正对楼梯下怎么办 电梯门对着家门怎么办 壁纸上的泡沫胶怎么办 卧室镜子对着门 怎么办 电视对着厨房门怎么办 厨房门对着大门怎么办