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

iOS-通过Model控制UITableView

作者: _LZZ_ | 来源:发表于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

    想必大家在iOS开发都有遇到过在一个UITableView中展示各式各样UITableViewCell,导致在UI...

  • iOS- UI事件传递& 响应

    UI视图相关重要知识点 传送带: iOS- UITableView重用机制 iOS- UITableView数据源...

  • Azalea\Model

    Model 模块虚类 ⚠️ Model 为抽象类,无法通过 new 方式实例化,仅通过 控制器 或其它 模块 的 ...

  • MVC、MVP、MVVM、MVPVM区别

    分析主要是通过它的控制链、控制流向,View 的变化如何反馈到Model,以及Model的变化如何作用到View上...

  • MVVM模式示例代码

    viewModel作为连接view与model之间的桥梁 , view与model互不相通!在控制器中先通过mod...

  • 5、DOM

    DOM Document Object Model 功能:用来控制页面中的内容,通过操作对象来控制页面内容。 DO...

  • UITableView:internal inconsiste

    关于控制台打印UITableView的internal inconsistency问题 当UITableView处...

  • 标签视图控制器

    iOS-个人整理15 - 标签视图控制器--UITabBarController iOS UITabBarCont...

  • BOM&DOM

    javacsript是通过访问BOM(Browser Object Model)对象来访问、控制、修改客户端(浏览...

  • DOM和BOM

    javacsript是通过访问BOM(Browser Object Model)对象来访问、控制、修改客户端(浏览...

网友评论

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

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