美文网首页
iOS-通过Model控制UITableView

iOS-通过Model控制UITableView

作者: LZZ_IOS | 来源:发表于2020-01-03 16:02 被阅读0次

    想必大家在iOS开发都有遇到过在一个UITableView中展示各式各样UITableViewCell,导致在UITableViewDelegate、UITableViewDataSource中的代码过于臃肿。本文也是想着分享本人在工作的一些拙见,还请大家不喜勿喷;

    一、源代码

    通过Model控制UITableView主要分为以下两个类文件:

    1、控制UITableView section的TableViewSectionModel

    TableViewSectionModel.h文件,可根据需要自行填充

    #import "TableViewRowModel.h"
    @interface TableViewSectionModel : NSObject
    
    @property (nonatomic,assign) BOOL hasHeader; //是否有tableviewHeaderView
    @property (nonatomic,assign) CGFloat headerHeight; //tableviewHeaderView高度
    @property (nonatomic,copy) NSString *headerViewName; // tableviewHeaderView名称
    @property (nonatomic,strong) id headerViewDataSource; // tableviewHeaderView数据
    
    @property (nonatomic,assign) BOOL hasFooter; //是否有tableviewFooterView
    @property (nonatomic,assign) CGFloat footerHeight; //tableviewFooterView高度
    @property (nonatomic,copy) NSString *footerViewName; // tableviewFooterView名称
    @property (nonatomic,strong) id footerViewDataSource; // tableviewFooterView数据
    
    @property (nonatomic,copy) NSArray <TableViewRowModel *> *rows;// 行模型
    
    @end
    

    TableViewSectionModel.m文件,我这里只设置了初始化属性,可根据需要自行填充

    @implementation TableViewSectionModel
    
    -(instancetype)init{
        if (self = [super init]) {
            [self _initValue];
        }
        return self;
    }
    
    -(void)_initValue{
        self.hasHeader = NO;
        self.headerHeight = CGFLOAT_MIN;
        self.headerViewName = @"";
    
        self.hasFooter = NO;
        self.footerHeight = CGFLOAT_MIN;
        self.footerViewName = @"";
        
        self.rows = [NSArray array];
    }
    
    @end
    

    2、控制UITableView row的TableViewRowModel

    TableViewRowModel.h文件,可根据需要自行填充

    @interface TableViewRowModel : NSObject
    
    @property (nonatomic,copy) NSString *cellName;//cell名称
    @property (nonatomic,assign) CGFloat cellHeight;//cell高度
    @property (nonatomic,strong) id cellModel;//cell数据模型
    
    @end
    

    TableViewRowModel.m文件中没有编写任何内容,所有这里我就没有展示

    二、实际应用

    假设实际应用UITableView中有OneCell、TwoCell、OtherCell跟OneSectionHeaderView与TwoSectionHeaderView,这些文件中只有一个函数

    -(void)reloadWithModel:(id)model;
    

    ViewController中代码如下:

    #import "ViewController.h"
    
    #import "OneCell.h"
    #import "TwoCell.h"
    #import "OtherCell.h"
    #import "OneSectionHeaderView.h"
    #import "TwoSectionHeaderView.h"
    #import "TableViewSectionModel.h"
    @interface ViewController () <UITableViewDataSource,UITableViewDelegate>
    
    @property (nonatomic,strong) UITableView *tableView;
    
    @property (nonatomic,strong) NSMutableArray <TableViewSectionModel *>*dataSource;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        [self _addSubviews];
        //假设是在请求数据
        [self _loadDataWithResults:nil];
    }
    
    -(void)_loadDataWithResults:(NSDictionary *)results{
        //这里的代码我一般放在处理JSON数据的地方
        {
            //设置Section Header
            TableViewSectionModel *sectionModel = [[TableViewSectionModel alloc] init];
            sectionModel.hasHeader = YES;
            sectionModel.headerHeight = 68.0f;
            sectionModel.headerViewName = @"OneSectionHeaderView";
            sectionModel.headerViewDataSource = [NSObject new];
            
            //设置Section Footer,与Header用法一致,我这里只设置了一个高度
            sectionModel.footerHeight = 8.0f;
            
            //设置Rows
            NSMutableArray *rows = [NSMutableArray array];
            for (NSInteger i = 0; i < 5; i ++) {
                TableViewRowModel *rowModel = [[TableViewRowModel alloc] init];
                rowModel.cellHeight = 100.0f;
                rowModel.cellName = @"OneCell";
                rowModel.cellModel = [NSObject new];
                [rows addObject:rowModel];
            }
            sectionModel.rows = rows.copy;
            [self.dataSource addObject:sectionModel];
        }
        {
            //设置Section Header
            TableViewSectionModel *sectionModel = [[TableViewSectionModel alloc] init];
            sectionModel.hasHeader = YES;
            sectionModel.headerHeight = 168.0f;
            sectionModel.headerViewName = @"TwoSectionHeaderView";
            sectionModel.headerViewDataSource = [NSObject new];
            
            //设置Section Footer,与Header用法一致,我这里只设置了一个高度
            sectionModel.footerHeight = 8.0f;
            
            //设置Rows
            TableViewRowModel *rowModel = [[TableViewRowModel alloc] init];
            rowModel.cellHeight = 50.0f;
            rowModel.cellName = @"TwoCell";
            rowModel.cellModel = [NSObject new];
            sectionModel.rows = @[rowModel];
            
            [self.dataSource addObject:sectionModel];
        }
        {
            TableViewSectionModel *sectionModel = [[TableViewSectionModel alloc] init];
            //设置Section Footer,与Header用法一致,我这里只设置了一个高度
            sectionModel.footerHeight = 8.0f;
            
            //设置Rows
            NSMutableArray *rows = [NSMutableArray array];
            for (NSInteger i = 0; i < 5; i ++) {
                TableViewRowModel *rowModel = [[TableViewRowModel alloc] init];
                rowModel.cellHeight = 130.0f;
                rowModel.cellName = @"OtherCell";
                rowModel.cellModel = [NSObject new];
                [rows addObject:rowModel];
            }
            sectionModel.rows = rows.copy;
            [self.dataSource addObject:sectionModel];
        }
        [self.tableView reloadData];
    }
    
    #pragma mark - UITableViewDataSource
    -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
        return self.dataSource.count;
    }
    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
        return self.dataSource[section].rows.count;
    }
    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        TableViewRowModel *rowModel = self.dataSource[indexPath.section].rows[indexPath.row];
        if ([rowModel.cellName isEqual:@"OneCell"]) {
            OneCell *cell = [tableView dequeueReusableCellWithIdentifier:rowModel.cellName];
            if (cell == nil) {
                cell = [[OneCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:rowModel.cellName];
            }
            [cell reloadWithModel:rowModel.cellModel];
            return cell;
        }else if ([rowModel.cellName isEqual:@"TwoCell"]) {
            TwoCell *cell = [tableView dequeueReusableCellWithIdentifier:rowModel.cellName];
            if (cell == nil) {
                cell = [[TwoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:rowModel.cellName];
            }
            [cell reloadWithModel:rowModel.cellModel];
            return cell;
        }else if ([rowModel.cellName isEqual:@"OtherCell"]) {
            OtherCell *cell = [tableView dequeueReusableCellWithIdentifier:rowModel.cellName];
            if (cell == nil) {
                cell = [[OtherCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:rowModel.cellName];
            }
            [cell reloadWithModel:rowModel.cellModel];
            return cell;
        }
        return [UITableViewCell new];
    }
    
    #pragma mark - UITableViewDelegate
    -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
        return self.dataSource[indexPath.section].rows[indexPath.row].cellHeight;
    }
    -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
        return self.dataSource[section].headerHeight;
    }
    -(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
        return self.dataSource[section].footerHeight;
    }
    -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
        TableViewSectionModel *sectionModel = self.dataSource[section];
        if (sectionModel.hasHeader) {
            if ([sectionModel.headerViewName isEqual:@"OneSectionHeaderView"]) {
                OneSectionHeaderView *headerView = [[OneSectionHeaderView alloc] init];
                headerView.frame = CGRectMake(0.0f, 0.0f, self.view.frame.size.width, sectionModel.headerHeight);
                headerView.backgroundColor = [UIColor whiteColor];
                [headerView reloadWithModel:sectionModel.headerViewDataSource];
                return headerView;
            }else if ([sectionModel.headerViewName isEqual:@"TwoSectionHeaderView"]) {
                TwoSectionHeaderView *headerView = [[TwoSectionHeaderView alloc] init];
                headerView.frame = CGRectMake(0.0f, 0.0f, self.view.frame.size.width, sectionModel.headerHeight);
                headerView.backgroundColor = [UIColor whiteColor];
                [headerView reloadWithModel:sectionModel.headerViewDataSource];
                return headerView;
            }
            
        }
        return nil;
    }
    
    #pragma mark - setter UI
    -(void)_addSubviews{
        [self.view addSubview:self.tableView];
    }
    
    #pragma mark - getter and setter
    -(UITableView *)tableView{
        if (_tableView == nil) {
            _tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
            _tableView.estimatedRowHeight = CGFLOAT_MIN;
            _tableView.estimatedSectionHeaderHeight = CGFLOAT_MIN;
            _tableView.estimatedSectionFooterHeight = CGFLOAT_MIN;
            _tableView.dataSource = self;
            _tableView.delegate = self;
        }
        return _tableView;
    }
    
    -(NSMutableArray<TableViewSectionModel *> *)dataSource{
        if(_dataSource == nil){
            _dataSource = [NSMutableArray array];
        }
        return _dataSource;
    }
    @end
    

    页面呈现


    image.png

    三、优缺点

    优点:结构更加清晰,代码轻微减少;
    缺点:用户交互需要更新UI时不方便;

    相关文章

      网友评论

          本文标题:iOS-通过Model控制UITableView

          本文链接:https://www.haomeiwen.com/subject/jvvzoctx.html