YHListKit
YHListKit 是一个基于 UICollectionView
的轻量级数据驱动列表框架,核心思想是通过适配器模式将繁琐的 UICollectionView
相关代理方法转换成数据驱动的接口,更贴近人类的思维方式,同时还将注册 cell 和 dequeue cell 的逻辑封装到内部。此外,还借助消息转发机制,将 UICollectionViewDelegate
、UIScrollViewDelegate
等代理方法转发出来,供外部业务方在需要时使用。
特性
- 基于
UICollectionView
的适配器,无需面对繁琐的 register -> data source -> dequeue 流程 - 真正的数据驱动
- 自动缓存 cell/section header/section footer 的高度
- 采用面向协议的设计,解耦
- 无需继承,即插即用,无侵入性
预览效果图
架构
原本实现一个列表需要与 UICollectionView
繁琐的 API 交互:
- 创建
UICollectionView
;- 注册 cell;
- 解析数据/组装数据;
- 至少实现 3 个代理方法,非常繁琐;
- 重新加载数据;
使用 YHListKit
后,只需与数据交互:
- 创建
UICollectionView
;- 解析数据/组装数据(包含视图模型);
- 创建
YHCollectionViewAdapter
,传入数据,绑定UICollectionView
;- 重新加载数据;
程序的本质是处理数据,UI 是数据的表现形式。对于软件工程师来说,最佳效果是编写一个配置文件就能看到效果。YHListKit
所做的是,删除解析数据之外的多余步骤,让我们只需关注数据,就是这么简单。
类、协议 | 功能 |
---|---|
YHCollectionViewCellModel、YHCollectionViewSectionModel | 代表 cell、section header 和 section footer 相关数据的视图模型 |
YHCollectionViewAdapter | 包装 UICollectionView 代理方法的核心类,将代理回调形式的接口转换成视图模型形式的数据驱动接口 |
YHCollectionViewCell、YHCollectionViewSectionHeaderFooter | 定义 cell 和 section header、footer 的通用接口,用于绑定视图模型数据,以及获取高度 |
MessageInterceptor | 处理消息转发的拦截器 |
使用方法
UICollectionView
的代码相同):
1. 创建 collection view(这一步与平时使用 self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds
collectionViewLayout:self.collectionViewLayout]; // 这里也可以使用自己的 layout
self.collectionView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.collectionView.backgroundColor = [UIColor colorWithRed:244 green:244 blue:244 alpha:1.0];
self.collectionView.alwaysBounceVertical = YES;
[self.view addSubview:self.collectionView];
YHCollectionViewAdapter
,绑定 collectionView,设置代理:
2. 创建 self.adapter = [[YHCollectionViewAdapter alloc] init];
self.adapter.collectionView = self.collectionView; // 绑定 collection view
self.adapter.collectionViewDelegate = self; // 设置代理不是必需的,视业务情况而定
self.adapter.delegate = self; // 设置代理不是必需的,视业务情况而定
UICollectionViewCell
中实现 YHCollectionViewCell
协议,手动合成 cellModel 属性(以 SCCutomCollectionViewCell
为例):
3. 在你的自定义 @interface SCCutomCollectionViewCell : UICollectionViewCell <YHCollectionViewCell>
@end
@implementation SCCutomCollectionViewCell
@synthesize cellModel = _cellModel;
@end
4. 设置 viewModel 数据,也就是创建 section model 和 cell model,配置相关数据(注:这里仅为例,你可以配置任何你想要展示的数据):
// 可以理解为一个 table view 的数据源由多个 section model 组成,每个 sectionModel 包括 header 和 footer 相关的信息、cell models、以及 section 本身的信息。详见 YHCollectionViewSectionModel 和 YHCollectionViewCellModel 的头文件。
NSMutableArray *sections = [NSMutableArray array];
for (int section = 0; section < 4; section++) {
BOOL hasMultiColumns = section % 2;
// 创建 section model
YHCollectionViewSectionModel *sectionModel = [[YHCollectionViewSectionModel alloc] init];
sectionModel.sectionIdentifier = [NSString stringWithFormat:@"section_id_%@", @(section)]; // 设置 section 的唯一标识,可选
NSMutableArray *rows = [NSMutableArray array];
for (int row = 0; row < 10; row++) {
// 创建 cell model
YHCollectionViewCellModel *cellModel = [[YHCollectionViewCellModel alloc] init];
cellModel.dataModel = [NSString stringWithFormat:@"%i - %i", section, row]; // 设置 model 数据
cellModel.cellClass = [SCCutomCollectionViewCell class]; // 设置 cell class
if (hasMultiColumns) {
cellModel.cellWidth = 160;
cellModel.cellHeight = 160;
} else {
cellModel.cellHeight = 70; // 设置 cell 高度,也可以在对应的 cell 中实现相应的协议方法来实现
}
[rows addObject:cellModel];
}
sectionModel.cellModels = rows; // 设置该 section 的 cell model 集合
sectionModel.headerClass = [SCCollectionSectionHeaderView class]; // 设置 section header 的 class
sectionModel.headerHeight = 50; // 设置 section header 的 高度
sectionModel.footerClass = [SCCollectionSectionFooterView class]; // 设置 section footer 的 class
sectionModel.footerHeight = 20; // 设置 section footer 的 高度
if (hasMultiColumns) {
// 还可以设置 section 的一些布局参数,比如实现一行两列的效果
sectionModel.sectionInsets = UIEdgeInsetsMake(10, 20, 10, 20);
sectionModel.minimumLineSpacing = 15;
}
[sections addObject:sectionModel];
}
// 传入数据
self.adapter.sectionModels = sections;
[self.collectionView reloadData];
YHCollectionViewCell
和 YHCollectionViewSectionHeaderFooter
协议中定义的方法即可(如果同时实现了两种方法,默认取后一种方法计算的值):
5. 设置 cell、section header 和 section footer 的高度有两种方法,除了在 viewModel 层设置之外,还可以在对应的 view 层设置高度,只需实现 @protocol YHCollectionViewCell <NSObject>
...
+ (CGFloat)cellHeightWithModel:(YHCollectionViewCellModel *)model;
+ (CGFloat)cellWidthWithModel:(YHCollectionViewCellModel *)model;
@end
@protocol YHCollectionViewSectionHeaderFooter <NSObject>
...
+ (CGFloat)heightWithModel:(YHCollectionViewSectionModel *)model;
+ (CGFloat)widthWithModel:(YHCollectionViewSectionModel *)model;
@end
更详细的使用说明请参见示例代码 示例。
问答
YHCollectionViewAdapter
的 controller 中与 cells 和 supplementary views 进行通信?
1. 如何在管理 第一步:将 YHCollectionViewAdapter
的 delegate
属性值设置为当前的 controller;
第二步:实现 YHCollectionViewAdapterDelegate
协议中的方法即可,该协议提供了两个方法分别用来与 cells 和 supplementary views 进行通信:
- (void)collectionViewAdapter:(YHCollectionViewAdapter *)adapter didDequeueCell:(UICollectionViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;
- (void)collectionViewAdapter:(YHCollectionViewAdapter *)adapter didDequeueSupplementaryView:(UICollectionReusableView *)view ofKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;
详见示例代码 Example。
YHCollectionViewAdapter
的 controller 中得到 UICollectionViewDelegate
和 UIScrollViewDelete
的方法回调?
2. 如何在管理 第一步:将 YHCollectionViewAdapter
的 collectionViewDelegate
属性值设置为当前的 controller;
第二步:根据你的需要去实现 UICollectionViewDelegate
和 UIScrollViewDelete
协议中的方法即可。
详见示例代码 Example。
安装
YHListKit 可以通过 CocoaPods 安装:
pod 'YHListKit'
也可以通过手动安装,下载源代码后,将 YHListKit
文件夹拖到项目中即可使用。
系统要求
该项目最低支持 iOS 7.0。
待办事项
- 注释和文档
- Swift 版本
- CocoaPods 支持
- Nib 支持
❤️
致谢感谢 bestswifter 和 IGListKit 提供的灵感。
如果您有好的想法和问题,欢迎提交 issue 和 pull request。
许可证
本项目中使用了 MIT 许可证。更多详情见 LICENSE 文件。