序
在objcio.cn中有一篇文章更輕量的 View Controllers.其中有一小節,是說把UITableview的datasource和delegate分離出Viewcontroller的。我也試著實現了一下,隨便把思路總結下~
DEMO
建議先下載demo,再結合下面的分析,會好理解點。地址https://github.com/Resory/RYDatasource
邏輯
既然我們要把UITableview的協議方法分離出來,就得有一個人去接,在這里我們把這個人叫
Datasource
。可以理解它為中間人
。這個中間人
就是以后實現UITableview協議方法的地方。要
中間人
實現UITableview協議方法,就得知道UITableview的數據
,復用
,事件
等要素。這些數據由Viewcontroller來傳。這三個要素分別定義為serverData
,cellIdentifiers
,configSelectedBlock
自此我們可以知道,只要Viewcontroller傳了
serverData
,cellIdentifiers
,configSelectedBlock
這三個基本參數,中間人
就可以實現UITableview協議方法了。
實現
- 在Viewcontroller.m中。我們命名了三個全局變量,如下代碼
(configSelectedBlock
不需要設置全局,到時候在函數中直接生成即可)
// Viewcontroller.m
@property (nonatomic, strong) NSMutableArray *serverData; // 服務器返回的數據
@property (nonatomic, strong) NSMutableArray *cellIdentifiers; // cell樣式標示
@property (nonatomic, strong) TDatasource *datasource; // 中間人
- 還是在Viewcontroller.m中.我們把
數據
,復用
,事件
設置好后,看看如何調用中間人
。
數據
// Viewcontroller.m
- (void)configData
{
// 服務器返回的數據
_serverData = [[NSMutableArray alloc] init];
// 實體設置
TModelOne *one = [[TModelOne alloc] init];
TModelOne *two = [[TModelOne alloc] init];
one.name = @"奇犽";
one.imageName = @"001.jpg";
two.name = @"拿尼加";
two.imageName = @"002.jgp";
[_serverData addObject:one];
[_serverData addObject:two];
}
復用
// Viewcontroller.m
- (void)configIdentifier
{
// cell復用設置
_cellIdentifiers = [[NSMutableArray alloc] init];
[_cellIdentifiers addObject:NSStringFromClass([TCellOne class])];
[_tableview registerNib:[TCellOne nib] forCellReuseIdentifier:_cellIdentifiers[0]];
}
初始化"中間人"
// Viewcontroller.m
- (void)configDataSource
{
// cell數據
[self configData];
// cell復用
[self configIdentifier];
// cell事件
RYCellSelectedBlock cellSelectedBlock = ^(id obj){
// cell點擊事件
[self cellSelectedWithObj:obj];
};
// 初始化dataSource
_datasource = [[TDatasource alloc] initWithServerData:_serverData
andCellIdentifiers:_cellIdentifiers];
_datasource.cellSelectedBlock = cellSelectedBlock;
}
- 把
中間人
設置為UITableview的協議方法執行者
// Viewcontroller.m
- (void)configTableView
{
// 把_dataSource設置成_tableview的代理,以后所有代理方法都在_dataSource實現
_tableview.delegate = _datasource;
_tableview.dataSource = _datasource;
_tableview.tableFooterView = [UIView new];
}
- 我們進去
中間人
看看它到底做了什么,下面的代碼可以清晰看到。中間人
除了多了初始化方法來接受數據外,其他方法都是UITableview的協議方法
// TDatasource.m
- (id)initWithServerData:(NSArray *)serverData
andCellIdentifiers:(NSArray *)identifiers
{
self = [super init];
if(self)
{
self.serverData = serverData; // 數據
self.cellIdentifiers = identifiers; // 復用
}
return self;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifiers[0]
forIndexPath:indexPath];
// cell的數據填充(cell的category方法)
[cell configCellWithEntity:self.serverData[indexPath.row]];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 80.0;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// cell點擊事件
self.cellSelectedBlock(indexPath);
}
- 最后我們來看下cell里面的方法,也是一眼能看懂的代碼··
#import "TCellOne.h"
#import "TModelOne.h"
@implementation TCellOne
- (void)awakeFromNib {
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)configCellWithEntity:(id)entity
{
if(entity)
{
TModelOne *model = entity;
self.name.text = model.name;
self.avartar.image = [UIImage imageNamed:model.imageName];
}
}
- 挫就挫吧,總得來張圖。。
奇犽~.png
最后
UITableview協議方法分離出Viewcontroller后,Viewcontroller確實清爽了不少。但同時也帶了不便,比如說又多了一個文件,又比如說cell的點擊事件就得用一個block來回調,如果是cell里面的子view的點擊事件就更不利索了。所以有利就有弊吧。還是得結合實際選擇最適合自己的開發方式~
如果你有疑問或者發現錯誤請留言給我
喜歡就點個贊,點個星什么的。3Q~~