• 玩转UITableView


    UITableView这个iOS开发中永远绕不开的UIView,那么就不可避免的要在多个页面多种场景下反复摩擦UITableView,就算是刚跳进火坑不久的iOS Developer也知道实现UITableView的数据源dataSource和代理delegate,写出一个UITableView也就基本OK了,但是这仅仅是写出一个UITableView而已,作为一个有想法的程序猿,要做的还有很多,如何利用UITableViewCell的重用机制,如何提高性能等,这些留在后面的系列中一一讲述,那么本文要解决的痛点又是什么呢?回答这个问题之前,我们先来看看上面提到的UITableView的两大核心:UITableViewDataSource、UITableViewDelegate!

    一、UITableViewDataSource

    UITableView需要一个数据源(dataSource)来显示数据,UITableView会向数据源查询一共有多少行数据以及每一行显示什么数据等。没有设置数据源的UITableView只是个空壳。凡是遵守UITableViewDataSource协议的OC对象,都可以是UITableView的数据源。查看源码:

    @required  // 必须实现
    
    // 每个section的行数
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
    
    // 第section分区第row行的UITableViewCell对象 
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
    
    @optional  // 可选实现
    
    // section个数,默认是1
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; 
    
    // 第section分区的头部标题
    - (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;    
    
    // 第section分区的底部标题 
    - (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
    
    // 某一行是否可以编辑(删除)  
    - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;
    
    // 某一行是否可以移动来进行重新排序 
    - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath;
    
    // UITableView右边的索引栏的内容  
    // return list of section titles to display in section index view (e.g. "ABCD...Z#")
    - (nullable NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView;                              
    UITableViewDataSourc
     
    二、UITableViewDelegate
    通常都要为UITableView设置代理对象(delegate),以便在UITableView触发一下事件时做出相应的处理,比如选中了某一行。凡是遵守了UITableViewDelegate协议的OC对象,都可以是UITableView的代理对象。一般会让控制器充当UITableView的dataSource和delegate。查看源码:
    @protocol UITableViewDelegate<NSObject, UIScrollViewDelegate>
    
    @optional
    
    // 每行高度
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
    
    // 每个section头部高度
    - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
    
    // 每个section底部高度
    - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;
    
    // 每个section头部自定义UIView
    - (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section; 
    
    // 每个section底部自定义UIView
    - (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;
    
    // 是否允许高亮
    - (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0);
    
    // 选中某行
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
    UITableViewDelegate

    到这里已经很明确了,在需要实现UITableView的控制器对象里,就不可避免的要设置数据源和设置代理,那么就不可避免的需要实现以上提到的那些代理方法,试想一下,如果不进行有效的封装,那极有可能每个需要UITableView的Controller里都有如下重复的代码行:

    #pragma mark - UITableViewDelegate
    - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
        return 0.000001;
    }
    
    - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
        return 0.000001;
    }
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
        return 0;
    }
    
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
        return 0.000001;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
        return 0;
    }
    
    - (UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
        return nil;
    }
    
    - (UIView*)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{
        return nil;
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"defaultType"];
        return  cell;
    }
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
        return;
    }
    
    // lazy load
    - (UITableView*)tableView{
        if (!_tableView) {
            _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, -64, KS_Width, KS_Heigth+64) style:UITableViewStyleGrouped];
            _tableView.delegate = (id)self;
            _tableView.dataSource = (id)self;
            [_tableView setSectionHeaderHeight:0];
            _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
            _tableView.showsVerticalScrollIndicator = NO;
            _tableView.showsHorizontalScrollIndicator = NO;
        }
        return _tableView;
    }
    重复代码块

    这已经是够灾难的了,如果在项目周期中再遇到某个或者多个页面设计UI设计频繁的变动,那简直不敢想象,哪怕每次只是一点小小的改动,也可能需要修改上面重复代码块中UITableViewDelegate的多个地方,如新插入一行row或者一个section,所有涉及到section或者row的地方或许都需要更改!!!

    OK,我现在可以回答上面的问题了,这边文章到底是做什么的?解决的痛点在那里?--- 解耦封装、简化代码、适者生存!

    从重复代码块我们可以看出,一般会让控制器充当UITableView的dataSource和delegate,那么既然要解耦,那么就要打破思维定式,让UITableView自己做自己的dataSource和delegate!毕竟我的地盘我做主嘛!其次将UITableViewCell进行block封装对象化,让其所有的属性都自我集成

    一、首先来看UITableViewCell的封装 -- ZTCoolTableViewCell

    @class UIView;
    @class UITableViewCell;
    @class UITableView;
    @class NSIndexPath;
    
    // 创建section头部 Or section底部的block
    typedef UIView *(^buildCell)(UITableView *tableView, NSInteger section);
    // 创建section对应的row数据源的block
    typedef UITableViewCell *(^buildCellInfo)(UITableView *tableView, NSIndexPath *indexPath);
    // 点击section对应row的事件block
    typedef void (^clickBlock)(UITableView *tableView, NSIndexPath *indexPath);
    // ZTCoolTableCellList刷新block
    typedef void (^refreshBlock)();
    
    @interface ZTCoolTableViewCell : NSObject
    
    // 行高度
    @property (nonatomic,assign) CGFloat height;
    // 构造行
    @property (nonatomic, copy) buildCell buildCell;
    
    @end
    
    @interface ZTCoolTableCellList : NSObject
    
    // 头部
    @property (nonatomic,strong) ZTCoolTableViewCell * headCell;
    // 底部
    @property (nonatomic,strong) ZTCoolTableViewCell * footCell;
    // 构造行
    @property (nonatomic,copy) buildCellInfo buildCellInfo;
    // 列高(等于0表示自适应)
    @property (nonatomic,assign) CGFloat cellHeigth;
    // 行数量
    @property (nonatomic,assign) NSInteger cellCount;
    // 行点击事件
    @property(nonatomic,copy) clickBlock clickBlock;
    // 刷新事件(适用于需要动态更新tableview布局:新增或者删减section/row)
    @property(nonatomic,copy) refreshBlock refreshBlock;
    // 行标识
    @property (nonatomic,copy) NSString *identifier;
    @property (nonatomic,copy) NSString *xibName;
    
    // 简单初始化 (单行cell)
    - (ZTCoolTableCellList *)initSimpleCell:(CGFloat)cellHeight
                                  buildCell:(buildCellInfo)buildCell
                                  clickCell:(clickBlock)clickCell;
    
    // 复杂初始化 - 不可刷新
    - (ZTCoolTableCellList *)initComplexCellNoRefresh:(CGFloat)headHeigth
                                            buildHead:(buildCell)buildHead
                                           footHeight:(CGFloat)footHeight
                                            buildFoot:(buildCell)buildFoot
                                           cellHeight:(CGFloat)cellHeight
                                            buildCell:(buildCellInfo)buildCell
                                            clickCell:(clickBlock)clickCell
                                            cellCount:(NSInteger)cellCount
                                           identifier:(NSString *)identifier
                                              xibName:(NSString *)xibName;
    
    // 复杂初始化 - 可刷新
    - (ZTCoolTableCellList *)initComplexCellHasRefresh:(CGFloat)headHeigth
                                             buildHead:(buildCell)buildHead
                                            footHeight:(CGFloat)footHeight
                                             buildFoot:(buildCell)buildFoot
                                            cellHeight:(CGFloat)cellHeight
                                             buildCell:(buildCellInfo)buildCell
                                             clickCell:(clickBlock)clickCell
                                           refreshCell:(refreshBlock)refreshCell
                                             cellCount:(NSInteger)cellCount
                                            identifier:(NSString *)identifier
                                               xibName:(NSString *)xibName;
    @end
    .h文件
    @implementation ZTCoolTableViewCell
    
    @end
    
    @implementation ZTCoolTableCellList
    
    // 简单初始化
    - (ZTCoolTableCellList *)initSimpleCell:(CGFloat)cellHeight
                                  buildCell:(buildCellInfo)buildCell
                                  clickCell:(clickBlock)clickCell{
        
        return [self initComplexCellNoRefresh:0 buildHead:nil footHeight:0 buildFoot:nil cellHeight:cellHeight buildCell:buildCell clickCell:clickCell cellCount:1 identifier:nil xibName:nil];
    }
    
    // 复杂初始化 - 不可刷新
    - (ZTCoolTableCellList *)initComplexCellNoRefresh:(CGFloat)headHeigth
                                            buildHead:(buildCell)buildHead
                                           footHeight:(CGFloat)footHeight
                                            buildFoot:(buildCell)buildFoot
                                           cellHeight:(CGFloat)cellHeight
                                            buildCell:(buildCellInfo)buildCell
                                            clickCell:(clickBlock)clickCell
                                            cellCount:(NSInteger)cellCount
                                           identifier:(NSString *)identifier
                                              xibName:(NSString *)xibName{
        
        if(headHeigth >0){
            self.headCell = [[ZTCoolTableViewCell alloc] init];
            self.headCell.height = headHeigth;
            self.headCell.buildCell = buildHead;
        }
        
        if(footHeight >0){
            self.footCell = [[ZTCoolTableViewCell alloc] init];
            self.footCell.height = footHeight;
            self.footCell.buildCell = buildFoot;
        }
        
        self.cellHeigth = cellHeight;
        self.buildCellInfo = buildCell;
        self.clickBlock = clickCell;
        self.cellCount = cellCount;
        self.identifier = identifier;
        self.xibName = xibName;
        
        return self;
    }
    
    // 复杂初始化 - 可刷新
    - (ZTCoolTableCellList *)initComplexCellHasRefresh:(CGFloat)headHeigth
                                             buildHead:(buildCell)buildHead
                                            footHeight:(CGFloat)footHeight
                                             buildFoot:(buildCell)buildFoot
                                            cellHeight:(CGFloat)cellHeight
                                             buildCell:(buildCellInfo)buildCell
                                             clickCell:(clickBlock)clickCell
                                           refreshCell:(refreshBlock)refreshCell
                                             cellCount:(NSInteger)cellCount
                                            identifier:(NSString *)identifier
                                               xibName:(NSString *)xibName{
        
        if(headHeigth >0){
            self.headCell = [[ZTCoolTableViewCell alloc] init];
            self.headCell.height = headHeigth;
            self.headCell.buildCell = buildHead;
        }
        
        if(footHeight >0){
            self.footCell = [[ZTCoolTableViewCell alloc] init];
            self.footCell.height = footHeight;
            self.footCell.buildCell = buildFoot;
        }
        
        self.cellHeigth = cellHeight;
        self.buildCellInfo = buildCell;
        self.clickBlock = clickCell;
        
        if(refreshCell){
            self.refreshBlock = refreshCell;
        }
        
        self.cellCount = cellCount;
        self.identifier = identifier;
        self.xibName = xibName;
        
        return self;
    }
    .m文件

    二、让UITableView自己做自己的dataSource和delegate -- ZTCoolTableViewBase

    @class ZTCoolTableCellList;
    
    @interface ZTCoolTableViewBase : UITableView <UITableViewDataSource, UITableViewDelegate>
    
    // UITableView的数据集合
    @property (nonatomic,strong) NSMutableArray<ZTCoolTableCellList*> *arrayTableViewCellList;
    
    @end
    .h文件
    @implementation ZTCoolTableViewBase
    
    #pragma mark-hitTest
    - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
        id view = [super hitTest:point withEvent:event];
        if(![view isKindOfClass:[UITextField class]]){
            [self endEditing:YES];
        }
        return view;
    }
    
    #pragma mark - TableViewDelegate
    // section头部高度
    - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
        ZTCoolTableCellList *cellList = [self.arrayTableViewCellList objectAtIndex:section];
        if(cellList.headCell){
            return cellList.headCell.height;
        }else{
            return 0.00001;
        }
    }
    
    // section底部高度
    - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
        ZTCoolTableCellList *cellList = [self.arrayTableViewCellList objectAtIndex:section];
        if(cellList.footCell){
            return  cellList.footCell.height;
        }else{
            return 0.00001;
        }
    }
    
    // 有多少section
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
        return [self.arrayTableViewCellList count];
    }
    
    // 改变行的高度
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
        ZTCoolTableCellList *cellList = [self.arrayTableViewCellList objectAtIndex:[indexPath section]];
        if(cellList.cellHeigth == 0){
            UITableViewCell *cell = [self tableView:self cellForRowAtIndexPath:indexPath];
            return cell.frame.size.height;
        }else{
            return cellList.cellHeigth;
        }
    }
    
    // 每个section有多少行
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
        ZTCoolTableCellList *cellList = [self.arrayTableViewCellList objectAtIndex:section];
        return cellList.cellCount;
    }
    
    // 头部
    - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
        ZTCoolTableCellList *cellList = [self.arrayTableViewCellList objectAtIndex:section];
        if(cellList.headCell.buildCell){
            return cellList.headCell.buildCell(tableView,section);
        }else{
            return nil;
        }
    }
    
    // cell数据构造
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        ZTCoolTableCellList *cellList = [self.arrayTableViewCellList objectAtIndex:[indexPath section]];
        return cellList.buildCellInfo(tableView,indexPath);
    }
    
    // 底部
    - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{
        ZTCoolTableCellList *cellList = [self.arrayTableViewCellList objectAtIndex:section];
        if(cellList.footCell.buildCell){
            return cellList.footCell.buildCell(tableView,section);
        }else{
            return nil;
        }
    }
    
    // 选中某个项
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
        ZTCoolTableCellList *cellList = [self.arrayTableViewCellList objectAtIndex:[indexPath section]];
        if(cellList.clickBlock){
            return cellList.clickBlock(tableView,indexPath);
        }
    }
    
    - (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0){
        return YES;
    }
    .m文件

    如此,我们便实现了UITableViewCell的对象化封装和Controller于UITableView数据源及代理的耦合。

    那么如何实际运用呢?我们来举个例子,如下图,实现这样一个页面:

     

    按照以前的思维,将控制器充当UITableView的dataSource和delegate,那么就会出现

    _tableView.delegate = (id)self;

    _tableView.dataSource = (id)self;

     而且每个Controller页面都是实现的协议代理方法,一长串的重复代码!!!

     那么现在有了新需求,需要动态的再第一个section和第二个section之间新增一个section,包括两行row,这就需要重新代码布局,涉及到了所有     row点击事件极有可能需要重新绑定section与row值,对于能躺着绝对不站着的懒程序猿来说,这简直不要太扎心!如果使用上面封装的设计去实现,简直不要太舒服!

    一、声明对象

    // 主界面容器UITableView
    @property (nonatomic,strong) ZTCoolTableViewBase   *tableView;
    // 第一个section(个人资料、我的钱包)
    @property (nonatomic,strong) ZTCoolTableCellList   *firstCell;
    // 第二个section(交易记录、联系客服、设置)
    @property (nonatomic,strong) ZTCoolTableCellList   *secondCell;
    // 第三个section(私人日记、统计面板)
    @property (nonatomic,strong) ZTCoolTableCellList   *thirdCell;

    二、设置UITableView数据源和代理

    - (ZTCoolTableViewBase *)tableView{
        if (!_tableView) {
            CGRect rect = [UIScreen mainScreen].bounds;
            _tableView = [[ZTCoolTableViewBase alloc] initWithFrame:rect style:UITableViewStyleGrouped];
            _tableView.arrayTableViewCellList = [[NSMutableArray alloc] initWithObjects:
                                                 self.firstCell,
                                                 self.thirdCell,
                                                 nil];
            _tableView.delegate = _tableView;
            _tableView.dataSource = _tableView;
            _tableView.sectionHeaderHeight = 0;
            _tableView.separatorColor = [UIColor groupTableViewBackgroundColor];
        }
        return _tableView;
    }

    其中:

    // 设置UITableView的代理为自己  
     _tableView.delegate = _tableView;
    // 设置UITableView的数据源为自己 
    _tableView.dataSource = _tableView;
    
    // 初始化UITableView的数据对象集合
     _tableView.arrayTableViewCellList = [[NSMutableArray alloc] initWithObjects:
                                                 self.firstCell,
                                                 self.thirdCell,
                                                 nil];

     三、懒加载数据集合

    #pragma mark - firstCell
    - (ZTCoolTableCellList *)firstCell{
        if (!_firstCell) {
            BIWeakObj(self)
            static NSString *identifier = @"firstCell";
            _firstCell = [[ZTCoolTableCellList alloc] init];
            _firstCell = [_firstCell initComplexCellNoRefresh:0 buildHead:nil footHeight:10 buildFoot:nil cellHeight:44 buildCell:^UITableViewCell *(UITableView *tableView, NSIndexPath *indexPath) {
                
                UITableViewCell *cell = [selfWeak.tableView dequeueReusableCellWithIdentifier:identifier];
                
                if(cell == nil){
                    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
                    cell.selectionStyle = UITableViewCellSelectionStyleNone;
                    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
                    cell.textLabel.font = [UIFont systemFontOfSize:14.0f];
                    
                    if(indexPath.row == 0){
                        cell.imageView.image = [UIImage imageNamed:@"ic_my_info"];
                        cell.textLabel.text = @"个人资料";
                    }
                    else{
                        cell.imageView.image = [UIImage imageNamed:@"ic_my_money"];
                        cell.textLabel.text = @"我的钱包";
                    }
                }
                
                return cell;
                
            } clickCell:^(UITableView *tableView, NSIndexPath *indexPath) {
                
                [selfWeak clickCell:indexPath];
                
            } cellCount:2 identifier:identifier xibName:nil];
        }
        return _firstCell;
    }
    firstCell
    #pragma mark - secondCell
    - (ZTCoolTableCellList *)secondCell{
        if (!_secondCell) {
            BIWeakObj(self)
            static NSString *identifier = @"secondCell";
            _secondCell = [[ZTCoolTableCellList alloc] init];
            _secondCell = [_secondCell initComplexCellNoRefresh:0 buildHead:nil footHeight:10 buildFoot:nil cellHeight:44 buildCell:^UITableViewCell *(UITableView *tableView, NSIndexPath *indexPath) {
                
                UITableViewCell *cell = [selfWeak.tableView dequeueReusableCellWithIdentifier:identifier];
                
                if(cell == nil){
                    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
                    cell.selectionStyle = UITableViewCellSelectionStyleNone;
                    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
                    cell.textLabel.font = [UIFont systemFontOfSize:14.0f];
                    
                    if(indexPath.row == 0){
                        cell.imageView.image = [UIImage imageNamed:@"ic_my_log"];
                        cell.textLabel.text = @"私人日记";
                    }
                    else{
                        cell.imageView.image = [UIImage imageNamed:@"ic_my_statistic"];
                        cell.textLabel.text = @"统计面板";
                    }
                }
                
                return cell;
                
            } clickCell:^(UITableView *tableView, NSIndexPath *indexPath) {
                
                [selfWeak clickCell:indexPath];
                
            } cellCount:2 identifier:identifier xibName:nil];
        }
        return _secondCell;
    }
    secondCell
    #pragma mark - thirdCell
    - (ZTCoolTableCellList *)thirdCell{
        if (!_thirdCell) {
            BIWeakObj(self)
            static NSString *identifier = @"thirdCell";
            _thirdCell = [[ZTCoolTableCellList alloc] init];
            
            _thirdCell = [_thirdCell initComplexCellHasRefresh:0 buildHead:nil footHeight:0 buildFoot:nil cellHeight:44 buildCell:^UITableViewCell *(UITableView *tableView, NSIndexPath *indexPath) {
                
                UITableViewCell *cell = [selfWeak.tableView dequeueReusableCellWithIdentifier:identifier];
                
                if(cell == nil){
                    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
                    cell.selectionStyle = UITableViewCellSelectionStyleNone;
                    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
                    cell.textLabel.font = [UIFont systemFontOfSize:14.0f];
                    
                    if(indexPath.row == 0){
                        cell.imageView.image = [UIImage imageNamed:@"ic_my_quotebill"];
                        cell.textLabel.text = @"交易记录";
                    }
                    else if(indexPath.row == 1){
                        cell.imageView.image = [UIImage imageNamed:@"ic_my_service"];
                        cell.textLabel.text = @"联系客服";
                    }
                    else{
                        cell.imageView.image = [UIImage imageNamed:@"ic_my_setup"];
                        cell.textLabel.text = @"设置";
                    }
                }
                
                return cell;
                
            } clickCell:^(UITableView *tableView, NSIndexPath *indexPath) {
                
                [selfWeak clickCell:indexPath];
                
            } refreshCell:^{
                
                [selfWeak.tableView.arrayTableViewCellList insertObject:selfWeak.secondCell atIndex:1];
                [selfWeak.tableView reloadData];
                
            } cellCount:3 identifier:identifier xibName:nil];
        }
        return _thirdCell;
    }
    thirdCell

    其中第三个cell可刷新(为了给第二个cell指定新增时的入口)这里是个block:

    refreshCell:^{
                
                [selfWeak.tableView.arrayTableViewCellList insertObject:selfWeak.secondCell atIndex:1];
                [selfWeak.tableView reloadData];
                
            }

    新增按钮点击事件:

    - (void)addTableviewSection:(id)sender{
        if(self.thirdCell.refreshBlock){
            self.thirdCell.refreshBlock();
        }
    }

    如此实现,在解耦的同时还能简化重复代码量,并且可以最小的代价cost适应频繁变化的UI设计!

    PS:目前的封装只支持每个section块的每行row高度是一样的,如果存在不一致的需求,可在我的基础上进行二次封装变化,如果我的文章对您有些许帮助,帮忙点赞标星,如需转载,请说明出处,谢谢!

    demo  Github地址:https://github.com/BeckWang0912/ZTCoolTableView  喜欢就标个星星吧✨✨~~~✨✨^o^

  • 相关阅读:
    linux下解压命令大全
    关于伸展树的详细解析(E文)
    数据结构与算法汇总
    Linux下的压缩解压缩命令详解
    Linux Netcat 命令——网络工具中的瑞士军刀
    gethostbyname
    Html 转化为 PDF
    返回一个表
    sqlserver创建函数
    取不同类别的第一条数据
  • 原文地址:https://www.cnblogs.com/beckwang0912/p/7082826.html
Copyright © 2020-2023  润新知