iOS开发之DataSource神奇魔法,优雅的写法让你轻松驾驭TableView
项目地址:https://github.com/cocbin/CBTableViewDataSource
简介
最近在重构之前写的代码的时候,发现基本每个viewController里面都有一段又臭又长的代码用于定义tableView的dataSource
和delegate
,于是我在想,有没有更优雅的方式来书写dataSource
,于是乎就产生了CBTableViewDataSource。
使用CBTableViewDataSource之前
// define a enum to split sectiontypedef 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 somethingreturn cell;case SECTION_TWO:// to do somethingreturn cell;case SECTION_THREE:// to do somethingreturn cell;//...}return cell;
}
// ...
使用CBTableViewDataSource 之后
CBTableViewDataSource * dataSource = CBDataSource(self.tableView).section().cell([OneCell class]).data(self.viewModel.oneData).adapter(^UITableViewCell *(OneCell * cell,NSDictionary * data,NSUInteger index){//bind data form data to cellreturn cell;}).section().cell([TwoCell class]).data(self.viewModel.twoData).adapter(^UITableViewCell *(TwoCell * cell,NSDictionary * data,NSUInteger index){//bind data form data to cellreturn cell;})// ....make();
CBTableViewDataSource允许我们以函数式的方式定义dataSouce,逻辑顺序和页面的呈现顺序一致。
每个section以section()开头,在section()之后,可以对该section进行一些配置,要求每个section必须设置cell,data,和adapter。cell表示该section使用的cell类,data表示该section的数据,adapter用于将数据和cell绑定起来。同时还能配置section中cell的高度,或者设置自动计算高度。也可是设置section的标题,cell的点击事件等等。
CBTableViewDataSource主要解决了以下几个问题:
- 避免了书写各种乱七八糟的宏定义,自动注册cell类,自动设置identifier。
- 提供了一套完美解决不同高度cell的计算问题,提供自动计算cell高度的接口。
- 提供一套优雅的api,十分优雅并且有逻辑地书写dataSource。
DEMO解读
DEMO包括两个页面,First展示了复杂多section页面时的用法,通过一个仿各种市面上流行的APP的首页,体现了该框架书写dataSource条理清晰,逻辑顺序和页面呈现的顺序完全一致的优点。
![](http://upload-images.jianshu.io/upload_images/633180-4ee9b5cfc2e08814.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![](http://upload-images.jianshu.io/upload_images/633180-037b1c2a9c3f20b9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
second页面通过一个Feed页面,展示了autoHeight的用法。只要调用autoHeight
函数,一句话解决cell高度计算问题。
![](http://upload-images.jianshu.io/upload_images/633180-ca210a360bb04b54.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
用法
Install
框架一共包括四个文件
CBDataSourceMaker.h
CBDataSourceMaker.mCBTableViewDataSource.h
CBTableViewDataSource.m
可以直接通过Pod下载使用
pod ....(还没上传)
或者直接将上述四个文件复制到你的项目中即可使用。
Import
#import <CBTableViewDataSource/CBTableViewDataSource.h>
声明
@property(nonatomic, retain) CBTableViewDataSource * dataSource;
初始化
_dataSource = CBDataSource(self.tableView).section().title(@"section one").cell([TestCell class]).data(array).adapter(^(TestCell * cell,NSDictionary * dic,NSUInteger index){cell.content.text = dic[@"content"];return cell;}).make()
!!!注意!!!
不能直接为dataSource赋值
//BAD
self.tableView.dataSource = CBDataSource(self.tableView).section().cell(...).data(...).adapter(...).make()
因为UITableView的dataSource声明的是weak,赋值完因为没有任何强引用导致它的内存会被直接释放。
API
CBDataSource(UITableView * tableView)
创建一个CBDataSourceMaker
对象,用于创建CBTableViewDataSource
,传入一个需要绑定该dataSource
的tableView
对象
section()
用于分割多个section,每个section的开头到要使用section()声明一个section的开始
cell(Class cell)
传入一个cell的class,如[UITableViewCell class]
。
表示当前section都使用这个cell,注意,cell不需要注册,框架会自动注册并绑定identifier
data(NSArray * data)
传入一个数组,表示用于呈现在界面上的数据
adapter(^
(id cell,id data,NSUInteger index))
适配器,使用该方法将数据和cell绑定起来。
参数是一个block,该block会传来一个cell对象,一个data对象,一个index。
可以直接在block上对参数类型进行强制转换。
如:
adapter(^(GoodsCell * cell,GoodsModel * goods,NSUInterger index){cell.goods = goods;return cell;
})
headerView(UIView(*^
**)())
设置tableHeaderView
参数是一个Block,要求返回一个UIView。
footerView(UIView*(^
)())
设置tableFooterView
参数是一个Block,要求返回一个UIView。
常用于取消当页面空白时,tableView呈现多余的下划线。
如:
footerView(^(){//返回一个空白View,这样页面没内容时或者内容不足一页,就不会出现多余的线条。return [[UIView alloc]init];
})
height(CGFloat * height)
单独为每个section设置一个固定的高度。
**有两个特例:**
- 当使用了autoHeight之后,该设置失效
- 当在所有section之前设置height,将为所有section公共的height
autoHeight()
自动计算cell高度,用于cell高度不固定的情况。
注意:
- 当cell的高度固定时,请不要使用autoHeight,因为autoHeight计算高度会消耗一定性能,尽管该框架已经对高度计算做了非常完美的缓存处理,但是对于高性能的追求一定要做到精益求精。
- 该设置只对autolayout有效。
一定要正确设置好约束:
- 所有cell里面的组件一定要放在cell.contentView里面,不然会计算错误
- 一定要有完整的约束。
确定一个约束是否完整有两个原则
- 对于cell内部每个独立的控件,都能确定位置和尺寸,比如左上角定在cell的左上角,然后设置高度宽度确定尺寸,或者设置右下角确定尺寸,前提是右下角相对的组件是能确定位置的。另外,UILabel和UIImageView,这种有内容的控件,只需要确定一个方向的尺寸,就会更具内容自动计算出另一个方向的尺寸,比如label知道宽度,和内容,就能算高度。
- 对于cell本身,必须能确定其尺寸。尺寸会通过约束其上下左右的控件来计算,这些所以约束其下和右的控件必须能确定位置和尺寸。值得说的是,这里很容易遗漏掉底部的约束,因为cell就算没有底部约束,也不会报错,但是不能满足计算出cell高度的必要条件。
event(^
(NSUInteger index,id data))
参数要求一个Block,用于设置cell的点击事件,index表示点击了当前section的index位置,data表示当前点击位置的数据。
title(NSString* title)
用于设置每个section的标题。
make()
在设置完毕之后执行,表示已经设置完毕了。
原文链接:http://www.jianshu.com/p/efca5a075b75
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
iOS开发之DataSource神奇魔法,优雅的写法让你轻松驾驭TableView相关推荐
- iOS开发之UI开发(UITableView)
UITableView 继承自UIScrollView,性能极佳 UITableView的两种样式 UITableViewStylePlain列表样式 UITableViewStyleGrouped ...
- iOS开发之AVKit框架使用
2019独角兽企业重金招聘Python工程师标准>>> iOS开发之AVKit框架使用 一.引言 在iOS开发框架中,AVKit是一个非常上层,偏应用的框架,它是基于AVFounda ...
- (0045) iOS 开发之MBProgressHUD 源码学习
(0045) iOS 开发之MBProgressHUD 源码学习 第一部分:学习所得和分析线程 1. 学习到了kvo 的使用 和屏幕方向的旋转判断. 2. 如果调起这个 HUD 的方法不是在主线程调 ...
- (0016)iOS 开发之Mac上Navicat Premium 创建远程连接和本地连接
1.下载安装 (百度云盘里面有安装文件和注册机) 链接: https://pan.baidu.com/s/1kVG1k71 密码: mr5g 破解教程看这篇博客:http://blog.csdn.ne ...
- 李洪强iOS开发之RunLoop的原理和核心机制
李洪强iOS开发之RunLoop的原理和核心机制 搞iOS之后一直没有深入研究过RunLoop,非常的惭愧.刚好前一阵子负责性能优化项目,需要利用RunLoop做性能优化和性能检测,趁着这个机会深入研 ...
- IOS开发之MD5加密和钥匙串的使用-oc
IOS开发之MD5加密和钥匙串的使用-oc 源码在我的主页,md5加密是用户登录安全的一个保障.不可逆的,可以暴力破解的. // // ViewController.m // MD5演练 // // ...
- IOS开发之CALayer基本属性和使用
IOS开发之CALayer基本属性和使用 // // ViewController.m // CALayer // // Created by 鲁军 on 2021/2/21. //#import & ...
- ios开发之plist 的文件的读写以及沙盒容器路径打印
ios开发之plist 的文件的读写以及沙盒容器路径打印 核心代码在这里 // // ViewController.m // 21-plist存储和沙盒路径 // // Created by 鲁军 o ...
- IOS开发之JSON文件的读写
IOS开发之JSON文件的读写 // // ViewController.m // 20-JSON的读写 // // Created by 鲁军 on 2021/2/13. //#import &qu ...
最新文章
- LeetCode-135-Candy
- ubuntu下安装redis
- Tooltip jqueryui
- OVS DPDK--网桥配置(四)
- CodeFrist基础_迁移更新数据
- java jdbc 详解_JDBC概述及详解各个对象
- 详解http和https的区别
- 前端面试准备---浏览器和网络篇(一)
- jcreator把class字节码文件转成.java源文件_如何将.JAVA文件编译成.CLASS文件.说明方法和工具,或用JCreator如何操作?...
- php手机电脑,php实现用手机关闭计算机(电脑)的方法
- Python urllib – Python 3 urllib
- Lucene.Net中 FSDirectory存储方式下一个 Document是如何得到的
- 服务器系统如何卸载IE,如何卸载ie浏览器,我来教您如何卸载ie浏览器的步骤
- html5实现统计功能,基于HTML5的统计图表系统的设计与实现
- java版12306抢票_J12306
- android vr sdk 架构,PowerVR图形SDK v4.0及工具终于问世
- 黑苹果(Hackintosh)简单步骤教程
- Android Studio 编译 UVCCamera
- 技术进化论,GITC2014来见证
- 时间分割算法,Java将一段时间按星期来分割
热门文章
- zcmu-1056 网址收藏夹
- 《现代控制理论》第5章
- onlyoffice-api
- 线上学微积,百度少不了
- SKU110K商品检测数据集处理
- android 获得手机MAC 和 IP
- Word在试图打开文件时遇到错误请尝试下列方法 *检查文档或驱动器的文件权限*确保有足够的内存和磁盘空间,...
- mysql阶梯统计_SQL技巧:利用阶梯式累加进行累计数量的计算 | 学步园
- 计算机看游戏显卡,电脑怎么看显卡参数_小编教你查看电脑显卡参数的方法-系统城...
- 中国移动网上商城有多坑?