Skip to content

基于系统tableView的自定义封装,快速构造,极简的代码风格,无需设置代理和数据源,与业务无关部分内部自动处理,包含无数据占位图,分页封装,网络错误占位图,点击重新加载等,大量减少重复代码。

License

Notifications You must be signed in to change notification settings

SmileZXLee/ZXBaseTableView

Repository files navigation

ZXBaseTableView

停止维护,推荐使用精简版的ZXTableView

创建一个常见的tableView示例

  • 首先我们创建一个ZXBaseTableView
//调用控制器分类中的creatTableView即可创建一个ZXBaseTableView,frame内部自动计算了。
ZXBaseTableView *tableView = [self creatTableView];
  • 告诉ZXBaseTableView需要显示的cell的类
tableView.cellClassAtIndexPath = ^Class(NSIndexPath *indexPath) {
    //如果是第0行,则显示XibTestCell,否则显示CustomTestCell,如果只有一个类型cell,不用判断indexPath
    if(indexPath.row == 0){
        return [XibTestCell class];
    }else{
        return [CustomTestCell class];
    }
};
  • 告诉ZXBaseTableView需要显示的HeaderView的类(FooterView亦然)
tableView.headerClassInSection = ^Class(NSInteger section) {
     return [TestHeaderView class];
};
  • 设置tableView中显示的数据的数组,和往常的设置数据源习惯一样,无需任何额外处理,self.dataArr中存放model数组(NSString之类的系统对象也可以),多级数组嵌套即为多section的情况。
tableView.zxDatas = self.dataArr;
  • 在XibTestCell与CustomTestCell中,设置cell中显示的数据,同样您无需更改习惯的设计模式,也无需继承任何自定义cell
    以XibTestCell为例,您只需在.h或.m中声明:
@property (strong, nonatomic) XibTestModel *testModel;   

(model的类名可以随便取,但是需要包含字符串“model”(大小写不影响),您也可以在配置文件ZXBaseTableViewConfig.h中更改这个设置)

然后重写model的set方法即可:

-(void)setXibTestModel:(XibTestModel *)testModel{
    _testModel = testModel;
    //在这里做数据赋值操作
    
}
  • 之后,我们可能需要获取tableView中对应cell的点击事件,并进行相应处理
//选中某一indexPath
tableView.didSelectedAtIndexPath = ^(NSIndexPath *indexPath,id model,UITableViewCell *cell) {
    NSLog(@"选中了%lu-%lu,选中model-%@,选中cell-%@",indexPath.section,indexPath.row,model,cell);
};

至此,一个普通的tableView已创建完毕,运行程序即可正常显示这个tableView,此示例可以适应大多数使用场景

ZXBaseTableView使用进阶

我们有些时候可能需要额外的处理,以下是较常见的其他关于tableView的处理:

  • 获取tableView中的cell,并进行额外处理
//获取对应indexPath的cell 可以在这里对cell赋值或者修改cell的一些属性或者绑定cell中button的点击事件
tableView.cellAtIndexPath = ^(NSIndexPath *indexPath, UITableViewCell *cell, id model) {
    if([cell isKindOfClass:[CustomTestCell class]]){
        ((CustomTestCell *)cell).backgroundColor = [UIcolor redColor];
    }
};
  • 获取ZXBaseTableView的headerView,可以做一些赋值操作
tableView.headerViewInSection = ^(NSUInteger section, UIView *headerView,  NSMutableArray *secArr) {
    if(section == 1){
        headerView.backgroundColor = [UIColor redColor];
    }
};
  • 手动设置cell高度(一般用不到)
tableView.cellHAtIndexPath = ^CGFloat(NSIndexPath *indexPath) {
    if(indexPath.row == 0){
        return 100;
    }else{
        return 60;
    }
};
  • 根据文字内容自动设置cell高度
//通常做法是在cell对应的model中定义一个用于存储cell高度的属性,重写cell中变化的文字内容的set方法,并且在set方法中将计算的高度结果赋值给cell高度的属性,ZXBaseTableView会为每个cell的对应model中动态添加一个名为cellH的属性,若用户手动创建了这个同名属性,则使用用户创建的cellH的值作为cell的高度,以下举例说明:
//假设cell对应的model中有一个comment属性,用于存储用户评论cell的评论内容,需要根据评论内容长度自动调整cell高度,则您只需要在model的.m文件中,写下如下代码即可,getRectHeightWithLimitH为自定义的计算文字高度的函数,需替换为自己的高度计算函数:
-(void)setComment:(NSString *)comment{
    _comment = comment;
    self.cellH = [comment getRectHeightWithLimitH:kScreenWidth - 10 * 2 fontSize:13];
}
//您需要model的在.h或.m中声明一下以下属性:
@property (nonatomic,assign) CGFloat cellH;
//大功告成!!
  • 在cell高度原本基础上修改cell高度,例如统一修改cell高度比例等,当然您也可以自定义model来处理这些,无需每个model都写一遍。
//您需要model的在.h或.m中声明一下以下属性:
@property (nonatomic,assign) CGFloat cellH;
//重写set方法即可,cellH即为原先计算好的cell高度或cell本身真实高度,您可以在这个基础上进行计算,赋值给_cellH即可
-(void)setCellH:(CGFloat)cellH{
    _cellH = cellH - 100;
    //_cellH = cellH * 0.8;
}
  • 在cell中获取当前indexPath
//您需要model的在.h或.m中声明一下以下属性:
@property (nonatomic,strong) NSIndexPath *index;
//则ZXBaseTableView会自动将当前模型的indexPath赋值给它,您可以在cell中通过对应模型获取对应的indexPath。
  • 创建headerView或footerView对象并设置为对应的headerView或footerView(不常用,一般直接返回对应对象名即可,ZXBaseTableView会自动创建并设置高度)
//声明tableView的footerView
tableView.viewForFooterInSection = ^UIView *(NSInteger section) {
    UILabel *footerLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, KSCREENWIDTH, 40)];
    footerLabel.textAlignment = NSTextAlignmentCenter;
    footerLabel.text = @"footerLabel";
    footerLabel.backgroundColor = [UIColor orangeColor];
    footerLabel.textColor = [UIColor whiteColor];
    return footerLabel;
};
//声明footerView高度
tableView.heightForFooterInSection = ^CGFloat(NSInteger section) {
    if(section == 3){
        return 40;
    }else{
        return 0.01;
    }
};
  • tableView滑动删除
tableView.editActionsForRowAtIndexPath = ^NSArray<UITableViewRowAction *> *(NSIndexPath *indexPath) {
    if(indexPath.row == self.dataSource.count)return nil;
    __weak typeof(self) weakSelf = self;
    UITableViewRowAction *deleteAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive   title:@"删除" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
        //对应删除操作
       
    }];
    return @[deleteAction];
 };
  • 有时候我们界面可能需要展示一些假数据,下面这个方法可以无需设置数据源数组即生成指定数量的cell
[tableView initDatasWithRowCount:20];
  • 禁止系统Cell自动高度 可以有效解决tableView跳动问题
tableView.disableAutomaticDimension = YES;
  • 同时支持系统原生的代理和数据源方法设置代理和数据源,遵循相应代理和数据源即可,若您重写了对应的代理方法,则对应的block方法将失效
tableView.zxDataSource = self;
tableView.zxDelegate = self;
  • 支持scrollView滚动事件,缩放事件,滚动到顶部事件,开始拖拽事件,正在拖拽事件等
tableView.scrollViewDidScroll = ^(UIScrollView *scrollView) {
    //NSLog(@"滚动到--%lf",scrollView.contentOffset.y);
};
//其他见ZXBaseTableView.h声明

ZXBaseTableView分页相关

大量减少重复的判断代码,控制中无需定义pageNo和pageCount,仅需将请求的结果传给ZXBaseTableView即可。
MJRefresh 是当前使用最为广泛的下拉刷新框架,ZXBaseTableView的分页模块基于此进行了一些处理,对暂无更多数据等footerView显示状态内部自动判断。再次表达对MJ老师的崇敬之情。

  • 告知ZXBaseTableView控制器中获取分页数据请求的方法即可
[self.tableView addPagingWithReqSel:@selector(reqDataList) target:self];
[self.tableView.mj_header beginRefreshing];
  • 请求分页数据(网络请求相关)
-(void)reqDataList{
    @ZXWeakSelf(self);
    [self reqLocalDtatWithParam:@{@"pageNo" : [NSNumber numberWithInteger:self.tableView.pageNo],@"pageCount" : [NSNumber numberWithInteger:self.tableView.pageCount]} resultBlock:^(BOOL result,id backData) {
        @ZXStrongSelf(self)
        if(result){
            //请求成功
            for (id data in (NSMutableArray *)backData) {
                [self.tableView.zxDatas addObject:data];
            }
        }
        
        //result = YES即为请求成功,需要告知ZXBaseTableView请求成功还是失败,若请求失败传入errDic,ZXBaseTableView会根据状态码显示对应的失败     页面,同时需要传入当前分页方法,点击ZXBaseTableView中的“重新加载”按钮时,会再次调用这个方法,请求失败pageNo不会增加。
        [self.tableView updateTabViewStatus:result errDic:backData backSel:@selector(reqDataList)];
    }];
    
}

至此,一个分页已经写完了,暂无数据占位图,网络错误占位图,点击重新加载,mjRefersh有数据显示下拉加载更多,无更多数据显示暂无更多数据等逻辑,内部已自动处理完毕了

ZXBaseTableView一些属性偏好设置

_若您需要修改ZXBaseTableView的默认配置或默认状态,在方法-initialize中设置即可

//无数据是否显示header 默认为NO
@property(nonatomic, assign)BOOL showHeaderWhenNoMsg;

//是否隐藏重新加载按钮 默认显示
@property(nonatomic, assign)BOOL hideReloadBtn;

//是否隐藏错误提示Toast 默认显示
@property(nonatomic, assign)BOOL hideMsgToast;

//是否固定错误提示占位图 默认为可以上下拖动
@property(nonatomic, assign)BOOL fixWhenNetErr;

其他详见ZXBaseTableView.h

ZXBaseTableView默认配置文件

///model默认去匹配的cell高度属性名 若不存在则动态生成cellHRunTime的属性名
static NSString *const CELLH = @"cellH";
///cell会自动赋值包含“model”的属性
static NSString *const DATAMODEL = @"model";
///model的index属性,存储当前model所属的indexPath
static NSString *const INDEX = @"index";
///若ZXBaseTableView无法自动获取cell高度(zxdata有值即可),且用户未自定义高度,则使用默认高度
static CGFloat const CELLDEFAULTH = 44;
///分页数量
static NSUInteger const PAGECOUNT = 10;

///暂无更多View宽度
static CGFloat const NOMOREDATAVIEWW = 150.0;
///暂无更多View高度
static CGFloat const NOMOREDATAVIEWH = 150.0;
///重新加载按钮宽度
static CGFloat const RELOADBTNW = 80.0;
///重新加载按钮高度
static CGFloat const RELOADBTNH = 25.0;
///重新加载按钮文字
static NSString *const RELOADBTNTEXT = @"重新加载";
///重新加载按钮主题色
static int const RELOADBTNMAINCOLOR = 0xe8412e;
///重新加载按钮上下间距
static int const RELOADBTNMARGIN = 10.0;
///重新加载按钮字体大小
static CGFloat const RELOADBTNFONTSIZE = 13.0;

///暂无更多数据图片
static NSString *const NOMOREDATAIMGNAME = @"nomoreDataImg";
///网络错误普遍处理图片
static NSString *const NETERRIMGNAME = @"netErrImg";

///网络错误特定处理图片与提示内容
///无网络连接
static NSString *const NETERRIMGNAME_NO_NET = @"noNetErrImg";
static NSString *const NETERRTOAST_NO_NET = @"无网络连接";
///请求失败
static NSString *const NETERRIMGNAME_REQ_ERROR = @"noNetErrImg";
static NSString *const NETERRTOAST_REQ_ERROR = @"请求失败";
///请求超时
static NSString *const NETERRIMGNAME_TIME_OUT = @"noNetErrImg";
static NSString *const NETERRTOAST_TIME_OUT = @"请求超时";
///请求地址出错
static NSString *const NETERRIMGNAME_ADDRESS_ERR = @"noNetErrImg";
static NSString *const NETERRTOAST_ADDRESS_ERR = @"请求地址出错";
///其他错误
static NSString *const NETERRIMGNAME_OTHER_ERR = @"";
static NSString *const NETERRTOAST_OTHER_ERR = @"未知错误";

///获取错误code的key
static NSString *const NETERR_CODE = @"code";
///获取错误message的key
static NSString *const NETERR_MESSAGE = @"message";

任何问题欢迎随时issue我,感谢!!

About

基于系统tableView的自定义封装,快速构造,极简的代码风格,无需设置代理和数据源,与业务无关部分内部自动处理,包含无数据占位图,分页封装,网络错误占位图,点击重新加载等,大量减少重复代码。

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published