只需一行代码,快速为UITableView创建Delegate和DataSource。
CBTableViewDataSource是一个轻量级的用于快速创建UITableView的DataSource和Delegate的框架。它提供了一些方便的API,帮助用户以一种快速和有逻辑的方式创建DataSource和Delegate。
最偷懒的使用方式如下:
[_tableView cb_makeSectionWithData:self.viewModel.data andCellClass:[CustomCell class]];没错,只需要一行代码。当然,使用这种方式需要遵循一定的约定。与此同时,我也提供了其他一些灵活的使用方式。具体详情请阅读以下文档。
我们在开发App的时候,往往花费大量的时间在为UITableView写DataSource和Delegate上。而它们往往是一些重复性的并且难以维护的代码。因为它们分散在了各个代理方法中,当我们需要进行修改时,需要到各个代理方法中依次修改它们。
而CBTableViewDataSource改变了这种书写方式,它提供一套简练的API,使得我们可以快速地书写有逻辑的,便于维护的代码。
为了让大家看到使用该框架的优势,我们来做一个对比:
使用原生方式创建DataSource和Delegate:
// Native vision
// define a enum to split section
typedef NS_ENUM(NSInteger, SectionNameDefine) {
SECTION_ONE,
SECTION_TWO,
SECTION_THREE,
SECTION_FOUR,
//...
COUNT_OF_STORE_SECTION
};
// define identifier for section
#define IDENTIFIER_ONE @"IDENTIFIER_ONE"
#define IDENTIFIER_TWO @"IDENTIFIER_TWO"
#define IDENTIFIER_THREE @"IDENTIFIER_THREE"
#define IDENTIFIER_FOUR @"IDENTIFIER_FOUR"
//...
// register cell class for section
[self.tableView registerClass:[OneCell class] forCellWithReuseIdentifier:IDENTIFIER_ONE];
[self.tableView registerClass:[TwoCell class] forCellWithReuseIdentifier:IDENTIFIER_TWO];
[self.tableView registerClass:[ThreeCell class] forCellWithReuseIdentifier:IDENTIFIER_THREE];
[self.tableView registerClass:[FourCell class] forCellWithReuseIdentifier:IDENTIFIER_FOUR];
// implementation datasource protocol
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return COUNT_OF_STORE_SECTION;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return ((NSArray*)self.data[section]).count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger section = (NSUInteger) indexPath.section;
NSUInteger index = (NSUInteger) indexPath.row;
switch(section) {
case SECTION_ONE:
// to do something
return cell;
case SECTION_TWO:
// to do something
return cell;
case SECTION_THREE:
// to do something
return cell;
//...
}
return cell;
}
// ...
可以看到,步骤多而繁琐,维护十分困难。
而使用CBTableViewDataSource后
[_tableView cb_makeDataSource:^(CBTableViewDataSourceMaker * make) {
// section one
[make makeSection:^(CBTableViewSectionMaker *section) {
section.cell([OneCell class])
.data(self.viewModel.oneDate)
.adapter(^(OneCell * cell,id data,NSUInteger index){
[cell configure:data];
})
.autoHeight();
}];
// section two
[make makeSection:^(CBTableViewSectionMaker *section) {
section.cell([TwoCell class])
.data(self.viewModel.twoData)
.adapter(^(FeedCell * cell,id data,NSUInteger index){
[cell configure:data];
})
.autoHeight();
}];
// ... so on
}];代码变得简练而富有层次感,更加符合人类的思维方式。
使用cocoapods下载
pod 'CBTableViewDataSource'#import <CBTableViewDataSource/CBTableViewDataSource.h>[_tableView cb_makeDataSource:^(CBTableViewDataSourceMaker * make) {
// section one
[make makeSection:^(CBTableViewSectionMaker *section) {
section.cell([OneCell class])
.data(self.viewModel.oneDate)
.adapter(^(OneCell * cell,id data,NSUInteger index){
[cell configure:data];
})
.autoHeight();
}];
// section two
[make makeSection:^(CBTableViewSectionMaker *section) {
section.cell([TwoCell class])
.data(self.viewModel.twoData)
.adapter(^(FeedCell * cell,id data,NSUInteger index){
[cell configure:data];
})
.autoHeight();
}];
// ... so on
}];UITableView tableView = [UITableView new];
[tableView cb_makeSectionWithData:data];使用该方式,Cell使用默认的UITableViewCell。
数据需要遵循以下约定:
- data是一个字典数组(NSArray< NSDictionary* >*)
- 字典键必须为以下5个键之一
text映射为UITableViewCell的textLabel的文字.detail映射为UITableViewCell的detailTextLabel的文字value映射为UITableViewCell的detailTextLabel的文字image映射为UITableViewCell的imageView的图片accessoryType设置UITableViewCell右边的样式
其中detail和value均映射为UITableViewCell的detailTextLabel的文字,如果键为detail,则detailTextLabel显示在textLabel底下。如果键为value,则detailTextLabel显示在cell右边。两者只能出现一个,优先级以第一个出现在数组中为先。
例如:
_data = @[
@{@"text":@"Following",@"value":@"45"},
@{@"text":@"Follower",@"value":@"10"},
@{@"text":@"Star",@"value":@"234"},
@{@"text":@"Setting",@"accessoryType":@(UITableViewCellAccessoryDisclosureIndicator)},
@{@"text":@"Share",@"accessoryType":@(UITableViewCellAccessoryDisclosureIndicator)}];则显示样式如下:
具体详情请下载该项目,查看DemoTwoViewController.h和DemoTwoViewController.m.
[tableView cb_makeSectionWithData:data andCellClass:[CustomCell class]];使用该方式,CustomCell需要提供一个Configuer:方法或者Configuer:index:方法用于适配数据.
例如:
- (void)configure:(NSDictionary *)row index:(NSNumber * )index {
if (row[@"avatar"]) {
[self.avatarView setImage:[UIImage imageNamed:row[@"avatar"]]];
} else {
[self.avatarView setImage:nil];
}
[self.nameLabel setText:row[@"name"]];
[self.titleLabel setText:row[@"title"]];
[self.detailLabel setText:row[@"detail"]];
self.circleView.hidden = row[@"unread"] == nil;
if([index intValue] &1) {
self.contentView.backgroundColor = [UIColor colorWithRed:0.95 green:0.96 blue:0.96 alpha:1.00];
} else {
self.contentView.backgroundColor = [UIColor whiteColor];
}
}具体用法请查看项目中CustomCell.h和CustomCell.m文件
页面样式如下:
详情请查看项目中DemoOneViewController.h和DemoOneViewController.m文件。
[tableView cb_makeSection:^(CBTableViewSectionMaker * section) {
section.data(@[]);
section.cell([CustomCell class]);
section.adapter(^(CustomCell cell,id row,NSUInteger index) {
cell.configure(row);
});
section.event(^() {
// do something
})
// other setting
}];这里展示的是单个section的情况。
注意,这些设置都是针对单独的section设置的
设置UITableView所要展示的数据。参数是一个NSArray。
如下:
section.data(@[@(goods1),@(goods2),...]);设置UITableView展示数据用的Cell Class。该Class会自动注册identifier,无需手动注册
如:
section.cell([CustomCell class]);用于适配Cell和Data,如:
section.adapter(^(CustomCell * cell,id row,NSUInteger index) {
[cell configure:row];
// ...
});
设置点击cell的响应事件。如:
section.event(^(NSUInteger index,id row) {
CustomViewController * controller = [CustomViewController new];
controller.viewModel.data = row;
[self.navigationController pushViewController:controller animated:YES];
});用于设置cell的高度。传一个固定的值。该高度只对该section有效。如:
section.height(100);设置自动动态计算cell高度。用于cell高度不一的场景。
section.autoHeight();该属性与height冲突,优先级是autoHeight > height。 也就是说当设置了autoHeight,则height失效,高度以autoHeight为准
设置section的headerTitle。用法如:
section.headerTitle("title");设置section的footerTitle。用法同上。
设置section的Header View。用法如下:
section.headerView(^(){
UIView * headerView = [UIView alloc]initWithFrame:CGRectMake(0,0,320,40);
// ...
return headerView;
})该属性与headerTitle冲突,当设置了headerView,以headerView为准。
设置section的Footer View。用法同上 该属性与footerTitle冲突,当设置了footerView,以footerView为准。
[tableView cb_makeDataSource:^(CBTableViewDataSourceMaker * make) {
[make headerView:^{
return [HeaderView new];
}];
[make makeSection: ^(CBTableViewSectionMaker * section) {
section.data(@[]);
section.cell();
section.adapter();
section.event();
// ... so on
}];
[make makeSection: ^(CBTableViewSectionMaker * section) {
section.data(@[]);
section.cell();
section.adapter();
section.event();
// ... so on
}];
[make makeSection: ^(CBTableViewSectionMaker * section) {
section.data(@[]);
section.cell();
section.adapter();
section.event();
// ... so on
}];
// .. so on
[make footView:^{
return [FooterView new];
}];
}]页面样式如下:
具体的代码请查看项目中DemoThreeViewController.h和DemoThreeViewController.m文件。
注意这些属性都是针对整个UITableView
用于为UITableView添加一个section。用法如下:
[tableView cb_makeDataSource:^(CBTableViewDataSourceMaker * make) {
[make makeSection: ^(CBTableViewSectionMaker * section) {
// ...
}
}]为整个UITableView的Cell设置默认高度。用法如下:
make.height(100);该属性与CBTableViewSectionMaker设置的height和autoHeight冲突。优先级是autoHeight > height(section) > height(UITableView)
也就是说,当一个section设置了autoHeight,则以autoHeight为准,其他section未设置autoHeight,而设置了height(section),则以height(section)为准,如果两者都没有,则以height(UITableView)为准。height默认为40。
设置UITableView的tableHeaderView,注意与section的headerView的区别,一个UITableView只有一个tableHeaderView。用法如下:
make.headerView(^(){
UIView * headerView = [[UIView alloc]init];
// ...
return headerView;
});设置UITableView的tableFooterView,同上。
设置UITableView的commitEditing代理方法,设置了该方法,则cell侧滑可以出现删除按钮。 可以在刚方法设置当cell处于编辑状态需要处理的事件。用法如下:
[make commitEditing:^(UITableView * tableView, UITableViewCellEditingStyle * editingStyle, NSIndexPath * indexPath) {
// do somethings.
}];设置UITableView的scrollViewDidScroll代理方法,当UITableView滚动时会调用该方法。 可以使用该方法处理UITableView的滚动事件。
[make scrollViewDidScroll:^(UIScrollView * scrollView) {
// do somethings
}];感谢您的使用和支持。欢迎issue和pull request,我会在第一时间内处理。
在这个框架中,我参考了许多大神们设计的框架。比如API的设计就参考了著名的AutoLayout框架Masonry。而在动态计算cell的高度上,则参考了@forkingdog的UITableView-FDTemplateLayoutCell的做法。
感谢他们带给我的灵感。
如有任何问题需要第一时间得到回答,请加交流群:481987249。




