优雅的开发TableView

前言

UITableView(UITableViewController)是iOS开发使用频率最高的一个组件。

不管是使用UITableView还是还是UITableViewController,在开发的时候,我们都需要实现两个协议:

  • UITableViewControllerDataSource
  • UITableViewControllerDelegate

这两个协议的代码不是写在Controller里就是写在ViewModel里,并且这些方法很难复用。关于Controller瘦身的更多细节,可以参我之前的一篇博客:

是否有一种更好的方式来开发TableView呢?如果是Model驱动,而不是代理方法驱动的就好了,如果是Model驱动,开发的时候只需要:

  • 创建Row和Section对应的Model
  • 由一个Manager去管理这些Model,并且对Client隐藏DataSource和Delegate方法
  • 把TableView绑定到Manager

基于这些理念,开发了一个model-driven-tableView框架,


问题

重复代码

Delegate/DataSource中,有许多重复的代码。比如:

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return _dataArray.count;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return 80.0;
}

这些代码的逻辑其实是一样的,一个section,一个数组作为Model,row的数量就是数组元素的个数。但是,很多时候我们都是在一个一个Controller之间进行copy/paste。

Render代码

通常,在cellForRowAtIndexPath或者willDisplay中,我们会对Cell进行重新配置,保证cell在复用的时候显示正确。于是,对Cell进行配置的代码耦合到了ViewController里,

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    YourCustomCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    if (cell == nil) {
        cell = [[YourCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
    }
    cell.leftLabel.text = titleArray[indexPath.row];
    cell.infoIcon.image = [UIImage imageNamed:imageArray[indexPath.row]];
    cell.rightLabel.text = rightArray[indexPath.row];
    return infoCell;
}

大量的if/else

当Cell的种类多了起来,或者点击cell的动作复杂起来,你会发现代码里充斥着各种各样的if/else(switch也一样)。大量的if/else导致代码难以阅读和维护。

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (section == 0) {
    }else if(section == 1){
    }else{
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == 0) {
    }else if(indexPath.section == 1){
    }else{
    }
}

这种情况,在设置界面尤其明显,比如这是网易云音乐的设置界面:

思考一下,如果让你来写,你会怎么写?


解决方案

基类

继承是一个实现代码复用的解决方案,通过在基类中实现-子类重写的方式进行服复用。

比如:

@interface SingleSectionTableViewController : UITableViewController
@property (strong, nonatomic)NSMutableArray * dataArray;
@end
@implementation SingleSectionTableViewController

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    [NSException raise:@"Com.t
  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值