前言
UITableView无疑是我们在开发iOS应用中使用频率非常高的一个控件,使用方法无外乎创建对象,关联delegate,datasource,实现对应方法.
几乎是在每一次使用UITableView的时候,都会去调用几个固定的方法,例如
//返回数量
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
//返回高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
//返回cell实例对象
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
//cell点击事件
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
这无疑是多了很多重复性质的代码,是否有办法可以简化UITableView的使用,避免这些重复性质的代码,同时能兼容大部分情况UITableView的使用呢?
将UITableView的Deleaget,DataSource抽离出来无疑是一个比较好的办法,实现一个通用的负责代理方法实现的类,通过block来回调,减少VC代码量.
代码实例
通用处理类CustomDeleagte.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef void (^TableViewCellConfigureBlock)(NSIndexPath* indexPath, id cell, id item);
typedef void (^TableViewCellDidSelectBlock)(NSIndexPath* indexPath, id cell, id item);
typedef CGFloat (^TableViewCellHeightBlock)(NSIndexPath* indexPath, id item);
@interface CustomDeleagte : NSObject <UITableViewDataSource,UITableViewDelegate>
- (id)initWithItems:(NSArray *)aItems
cellIdentifier:(NSString *)aIdentifier
configureCellBlock:(TableViewCellConfigureBlock)aConfigureCellBlock
cellHeightBlock:(TableViewCellHeightBlock)aHeightBlock
didSelectBlock:(TableViewCellDidSelectBlock)aDidSelectBlock;
- (void)handleTableViewDataSourceAndDelegate:(UITableView*)aTableView;
- (id)itemAtIndexPath:(NSIndexPath *)indexPath;
@property (nonatomic, copy) NSArray *items;
@end
1.TableViewCellConfigureBlock
用于传入数据源,加载数据
2.TableViewCellDidSelectBlock
回调点击事件
3.TableViewCellHeightBlock
计算cell高度
三个block基本涵盖了UITableView的一般使用.
通用处理类实现CustomDeleagte.m
#import "CustomDeleagte.h"
#import "UITableViewCell+Extension.h"
@interface CustomDeleagte()
@property (nonatomic, copy) NSString* cellIdentigier;
@property (nonatomic, copy) TableViewCellConfigureBlock configureCellBlock;
@property (nonatomic, copy) TableViewCellDidSelectBlock didSelectBlock;
@property (nonatomic, copy) TableViewCellHeightBlock heightBlock;
@end
@implementation CustomDeleagte
- (id)initWithItems:(NSArray *)aItems
cellIdentifier:(NSString *)aIdentifier
configureCellBlock:(TableViewCellConfigureBlock)aConfigureCellBlock
cellHeightBlock:(TableViewCellHeightBlock)aHeightBlock
didSelectBlock:(TableViewCellDidSelectBlock)aDidSelectBlock{
self = [super init];
if (self) {
self.items = aItems;
self.cellIdentigier = aIdentifier;
self.configureCellBlock = aConfigureCellBlock;
self.heightBlock = aHeightBlock;
self.didSelectBlock = aDidSelectBlock;
}
return self;
}
- (id)itemAtIndexPath:(NSIndexPath*)indexPath{
return self.items[(NSUInteger)indexPath.row];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.items.count;
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentigier];
if (!cell) {
[UITableViewCell registerTabelView:tableView nibIdentifier:self.cellIdentigier];
cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentigier];
}
id item = [self itemAtIndexPath:indexPath];
self.configureCellBlock(indexPath,cell,item);
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
id item = [self itemAtIndexPath:indexPath];
id cell = [tableView cellForRowAtIndexPath:indexPath];
self.didSelectBlock(indexPath,cell,item);
}
//注册delegate,datasource
- (void)handleTableViewDataSourceAndDelegate:(UITableView *)aTableView{
aTableView.delegate = self;
aTableView.dataSource = self;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
id item = [self itemAtIndexPath:indexPath];
return self.heightBlock(indexPath,item);
}
@end
给UITableViewCell扩展几个方法
UITableViewCell+Extension.h
#import <UIKit/UIKit.h>
@interface UITableViewCell (Extension)
//注册cell
+ (void)registerTabelView:(UITableView*)aTable
nibIdentifier:(NSString*)identifier;
//载入数据
- (void)configure:(UITableViewCell*)aCell
custimObj:(id)obj
indexPath:(NSIndexPath*)indexPath;
//根据数据源计算cell高度 默认返回44.0f
+ (CGFloat)getCellHeightWitCustomObj:(id)obj
indexPath:(NSIndexPath*)indexPath;
@end
UITableViewCell+Extension.m
#import "UITableViewCell+Extension.h"
@implementation UITableViewCell (Extension)
//注册cell
+ (void)registerTabelView:(UITableView*)aTable
nibIdentifier:(NSString*)identifier{
[aTable registerNib:[UINib nibWithNibName:identifier bundle:nil] forCellReuseIdentifier:identifier];
}
//载入数据
- (void)configure:(UITableViewCell*)aCell
custimObj:(id)obj
indexPath:(NSIndexPath*)indexPath{
}
//根据数据源计算cell高度 默认返回44.0f
+ (CGFloat)getCellHeightWitCustomObj:(id)obj
indexPath:(NSIndexPath*)indexPath{
return 44.0f;
}
@end
在自定义cell的类中重写这两个方法
configure
用于数据加载
getCellHeightWitCustomObj
用于计算高度
registerTabelView
方法在CusetDelegate中用于注册cell到对应tableView
代码中的使用方法
self.data = [[NSArray alloc]init];
self.tab = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight) style:UITableViewStylePlain];
TableViewCellConfigureBlock ConfigBlock = ^(NSIndexPath* indexPath,WelfareRuleCell* cell,id item){
[cell configure:cell custimObj:item indexPath:indexPath];
};
TableViewCellDidSelectBlock DidBlock = ^(NSIndexPath* indexPath,id cell,id item){
};
TableViewCellHeightBlock heightBlock = ^CGFloat(NSIndexPath* indexPath,id item){
return [WelfareRuleCell getCellHeightWitCustomObj:item indexPath:indexPath];
};
self.customDelegate = [[CustomDeleagte alloc]initWithItems:_data
cellIdentifier:@"WelfareRuleCell"
configureCellBlock:ConfigBlock
cellHeightBlock:heightBlock
didSelectBlock:DidBlock];
[self.customDelegate handleTableViewDataSourceAndDelegate:self.tab];
[self.view addSubview:self.tab];
自定义cell类
#import "WelfareRuleCell.h"
@implementation WelfareRuleCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)configure:(UITableViewCell *)aCell custimObj:(id)obj indexPath:(NSIndexPath *)indexPath{
//数据加载
self.XXX = XXX;
}
+ (CGFloat)getCellHeightWitCustomObj:(id)obj indexPath:(NSIndexPath *)indexPath{
//计算高度的代码
return xxx;
}
@end
后语
使用抽离Delegate和DataSource的方法来使用tableView,控制器中的代码可以被大大的简化,代码逻辑也能更清晰