HDTableViewMaker 1.0.9

HDTableViewMaker 1.0.9

测试已测试
语言语言 Obj-CObjective C
许可 MIT
发布最新发布2017年11月

AbnerH 维护。



 
依赖
MJRefresh>= 0
UITableView+FDTemplateLayoutCell>= 0
Masonry>= 0
 

  • 作者
  • Abner

HDTableViewMaker 中文文档

demo

仅一行代码,快速配置 UITableView 的所有配置(最终目标),包括创建 DelegateDataSource,集成刷新等功能。

简介

HDTableViewMaker 是一个轻量级的框架,用于快速配置 UITableView。它提供了一些方便的 API,帮助用户以一种快速和逻辑集中的方式配置出想要的 UITableView

为什么使用

在开发应用时,我们通常花费大量时间在为 UITableView 编写 DataSourceDelegate 上。而它们往往是一些重复性且难以维护的代码。因为它们分散在各个代理方法中,当我们需要修改时,需要依次修改各个代理方法。

HDTableViewMaker 改变了这种方式,它提供了一套简洁的 API,使得我们可以快速编写具有逻辑性、层次感,且易于维护的代码。

为了让大家看到使用该框架的优势,我们来做一个对比:

使用原生方式创建 DataSourceDelegate

// 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;
}
// ...

可以看到,步骤多而繁琐,最让我受不了的是这种逻辑的分离,特别是在 MVVM 模式中严重影响了代码的内聚,而且十分难以维护。
而使用 HDTableViewMaker

    [[_mainTable hd_tableViewMaker:^(HDTableViewMaker *tableViewMaker) {
        
        tableViewMaker.hd_sectionCount(1).hd_sectionMaker(^(HDSectionMaker * sectionMaker){
            
            sectionMaker.hd_dataArr(^(){
                return self.dataArr;
            }).hd_cellMaker(^(HDCellMaker *cellMaker){
                
                cellMaker.hd_cellClass([HDTableViewCell class]).hd_adapter(^(HDTableViewCell *cell,id data,NSIndexPath *indexPath){
                    cell.title = data;
                }).hd_autoHeight();
                
            });
        });
    }] hd_addAllFresh:^(HDFreshType freshType) {
        
    }];

可以看到代码变得简练而层次分明,更加符合人类的思维方式。而且这些配置都支持无序配置的,不管你先设置什么后设置什么,最终的效果都是一样的,所以想怎么设置就怎么设置吧。

关于框架后续以及框架性能

编写这个框架的初衷是想把 UITableView 这个在 iOS 开发中最常用同时也最难处理的东西简化起来,通过三言两语的配置就能展示出自己想要的效果,并且整合一些在 UITableView 上常用的功能,接下来会打算实现全屏的 loading 以及 empty set。
框架实现是通过封装存储了配置时设置的属性,在一定的时机读取这些配置而已,所以性能上只是多了存储了一些变量。

用法

安装

使用 cocoapods 下载

pod 'HDTableViewMaker'

导入包

#import <HDTableViewMaker/HDTableViewMakerHeader.h>

创建 DataSourceDelegate 并添加刷新控件

       [[_mainTable hd_tableViewMaker:^(HDTableViewMaker *tableViewMaker) {
        
        tableViewMaker.hd_sectionCount(1).hd_sectionMaker(^(HDSectionMaker * sectionMaker){
            
            sectionMaker.hd_dataArr(^(){
                return self.dataArr;
            }).hd_cellMaker(^(HDCellMaker *cellMaker){
                
                cellMaker.hd_cellClass([HDTableViewCell class]).hd_adapter(^(HDTableViewCell *cell,id data,NSIndexPath *indexPath){
                    cell.title = data;
                }).hd_autoHeight();
                
            });
        });
    }] hd_addAllFresh:^(HDFreshType freshType) {
        
    }];

HDTableViewMaker 支持设置以下属性:

注意,这些属性都是针对整个 UITableView

hd_sectionCount

用户配置这个 tableView 中存在几个 section

  dataSourceMaker.hd_sectionCount(10)
hd_sectionMaker

用于为 UITableView 配置每一个 section。用法如下:

    [_mainTable hd_tableViewMaker:^(HDTableViewMaker *tableViewMaker) {
        
        tableViewMaker
        .hd_sectionMaker(^(HDSectionMaker * sectionMaker){
            //...
        });
    }];
    
hd_height

为整个 UITableView 的 Cell 设置默认高度。用法如下:

tableViewMaker.hd_height(100);

该属性与 HDSectionMaker 和 HDCellMaker 设置的 hd_height 和 hd_autoHeight 冲突。优先级是 autoHeight(cell) > height(cell) > height(section) > height(UITableView)

也就是说,当一个 cell 设置了 autoHeight,则以 autoHeight 为准,其他 cell 未设置 autoHeight 而设置了 height(cell),则以 height(cell)为准,如果两者都没有,则以 height(section)为准。类推。height 默认为 40。

hd_headerView

设置 UITableView 的 tableHeaderView,注意与 section 的 headerView 的区别,一个 UITableView 只有一个 tableHeaderView。用法如下:

make.hd_headerView(^(){
    UIView * headerView = [[UIView alloc]init];
    // ...
    return headerView;
});
footerView

设置 UITableView 的 tableFooterView,同上。

hd_commitEditing

设置 UITableView 的 commitEditing 代理方法,设置了该方法,则 cell 侧滑可以出现删除按钮。
可以在该方法中设置当 cell 处于编辑状态时需要处理的事件。用法如下:

 [make commitEditing:^(UITableView * tableView, UITableViewCellEditingStyle * editingStyle, NSIndexPath * indexPath) {
    // do somethings.                
}];
hd_scrollViewDidScroll

设置 UITableView 的 scrollViewDidScroll 代理方法,当 UITableView 滚动时会调用该方法。
可以使用该方法处理 UITableView 的滚动事件。

[make scrollViewDidScroll:^(UIScrollView * scrollView) {
    // do somethings                
}];

HDSectionMaker 对象支持设置以下属性:

注意,这些设置都是针对单独的 section 设置的

hd_dataArr

设置该 section 中要展示的数据。参数是一个返回 NSArray。
这样在外界的 dataArr 发生变化后调用 reload 就可能刷新整个 UITableView 了。
如下:

sectionMaker.hd_dataArr(^(){
                return self.dataArr;
            }).
hd_headerTitle;

设置 section 的 headerTitle。用法如:

section.hd_headerTitle("title");
hd_footerTitle;

设置 section 的 footerTitle。用法同上。

hd_headerView;

设置 section 的 Header View。用法如下:

section.hd_headerView(^(){
    UIView * headerView = [UIView alloc]initWithFrame:CGRectMake(0,0,320,40);
    // ...
    return headerView;
})

该属性与 headerTitle 冲突,当设置了 headerView,以 headerView 为准。

hd_footerView;

设置 section 的 Footer View。用法同上
该属性与 footerTitle 冲突,当设置了 footerView,以 footerView 为准。

HDCellMaker 对象支持设置以下属性:

注意,这些设置都是针对单独的 cell 设置的

hd_cellClass

设置 UITableView 展示数据用的 Cell Class。该 Class 会自动注册 identifier(XIB),无需手动注册

如:

make.hd_cellClass([CustomCell class]);
hd_adapter

用于适配 CellData,做过安卓的应该很熟悉这个词。如

cell.hd_adapter(^(CustomCell * cell,id data,NSIndexPath *indexPath) {
    [cell configure:data];
    // ...
});
hd_event

设置点击 cell 的响应事件。如:

make.hd_event(^(NSIndexPath *indexPath,id data) {
    CustomViewController * controller = [CustomViewController new];
    controller.viewModel.data = data;
    [self.navigationController pushViewController:controller animated:YES];
});
hd_height

用于设置 cell 的高度。传一个固定的值。该高度只对该 cell 有效。如:

make.hd_height(100);
hd_autoHeight

设置自动动态计算 cell 高度。用于 cell 高度不一的场景。

make.hd_autoHeight();

该属性与 height 冲突,优先级是 autoHeight > height。
也就是说,当设置了 autoHeight,则 height 失效,高度以 autoHeight 为准

关于上拉下拉刷新的配置

#####hd_addFreshHeader
添加头部刷新
#####hd_addFreshFooter
添加上拉加载更多
#####hd_addAllFresh
全部添加
#####hd_endFreshing
结束刷新、注意的是参数 existMoreData,如果是 YES,则可以上拉加载更多,如果是 NO 则上拉加载更多会自动变成已经加载全部数据。在数据源为空时会自动隐藏加载更多控件

鸣谢

感谢您的使用和支持。欢迎 issue 和 pull request,我会在第一时间内处理。

在这个框架中,我参考了许多大师们设计的框架。比如 API 的设计就参考了著名的 AutoLayout 框架 Masonry。而在动态计算 cell 的高度上,则使用了 @forkingdogUITableView-FDTemplateLayoutCell 大法。刷新控件使用了大家都在用的 MJRefresh。

感谢他们带给我的灵感。

如果有任何问题需要立刻得到解答,请添加QQ:9395220。