【iOS开发】路由+协议打造极简 table view 和 collection view 页面

好久没有写东西了,今天来分享一下最近在项目中对UITableView的一种优化写法。

先来看一下效果

效果图

上面这个页面对应的ViewController的代码是这样的, Demo地址在文章的末尾:

#import "ViewController.h"
#import "YTTableView.h"
#import "ViewModel.h"

@interface ViewController ()

@property (nonatomic, strong) YTTableView *tableView;
@property (nonatomic, strong) ViewModel *viewModel;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self.view addSubview:self.tableView];
    self.tableView.frame = self.view.bounds;
    
    [self bindActions];
    
    self.tableView.sections = self.viewModel.sections;
}

- (void)bindActions {
    
    /*
     
     关于事件处理:
     1、建议项目用路由,cell的事件直接在cell内部处理掉。
     2、如果不用路由,如果cell上有个button什么的,点击要处理,可以在cell的view model里面声明对应的RACSignal。再进行订阅。点击button的时候,发送事件就可以处理了。
     3、cell的点击处理还可以用下面的这个didSelectRow来处理。
     
     */
    self.tableView.didSelectRow = ^(id viewModel, NSString *sectionKey) {
        // 点击事件在这里处理
    };
}

#pragma mark - lazy load

- (YTTableView *)tableView {
    if (!_tableView) {
        _tableView = [[YTTableView alloc] init];
        _tableView.backgroundColor = [UIColor colorWithRed:0xef/255.0 green:0xef/255.0 blue:0xef/255.0 alpha:1];
        _tableView.tableFooterView = [UIView new];
        _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    }
    
    return _tableView;
}

- (ViewModel *)viewModel {
    if (!_viewModel) {
        _viewModel = [ViewModel new];
    }
    
    return _viewModel;
}

@end

适用场景

任何用tableView的地方都可以用。

一般的开发写法

要在ViewController里面引入所有类型的cell,在cellForRow方法里面使用。注册cell使用。heightForRow方法也是各种判断(前面写了一篇文章减少判断的【iOS开发】UITableView和UICollectionView多种类型cell处理,更好地组织代码),增加或者减少某个类型的cell的时候,得去ViewController里面的好几个地增加或者减少代码。

YTTableView

优点

  • 完全解耦cell和view controller。
  • 方便版本迭代:新版本有新的样式或是要添加新的section 什么的,都可以不用改动viewController。
  • cell有极高的可重用性,实现了对应的协议后,任何地方都可以用。
  • 不需要修改ViewController里面的代码。
  • 任何的修改都可以在一个地方完成。
  • 集成了table view的分隔线,可以任意调整分隔线。section的第一条和最后一条分隔线可以分开设置。

cell的事件处理

  1. 建议项目用路由,cell的事件直接在cell内部处理掉。
  2. 如果不用路由,如果cell上有个button什么的,点击要处理,可以在cell的view model里面声明对应的RACSignal。再进行订阅。点击button的时候,发送事件就可以处理了。
  3. cell的点击处理还可以用YTTableView暴露的didSelectRow来处理。

集成使用

把YTTableView相关代码拉到项目中,pod支持找时间加上去。

注意的点:

  1. 如果用YTTableView中的自定义的分隔线,记得把table view本来的分隔线去掉。
  2. cell都要有一个对应的cell view model。
  3. cell 要实现YTCellProtocol协议。
  4. cell view model 要实现 YTTableCellViewModelProtocol协议。

协议说明

  • YTCellProtocol table view的cell都要实现这个接口,接口提供配置数据的方法和注册cell的方法。
/**
 cell 的接口
 提供一个配置cell的ViewModel的方法
 */
@protocol YTCellProtocol <NSObject>

@required


/**
 通过 view model 来配置cell, table view 的数据源里面装的都会是 view model
 
 @param viewModel cell 对应的 view model
 */
- (void)configCellWithViewModel:(id)viewModel;


@end
  • YTTableCellViewModelProtocol table view cell 对应的view model 都要实现这个接口,实现返回cell高度的方法和cell的复用id
/**
 UITableViewCell 对应的ViewModel 的协议
 */
@protocol YTTableCellViewModelProtocol <NSObject>

@required;
/**
 返回cell的高度, 这个方法是在view model中实现,view model中有cell的全部数据,所以这里可以通过数据计算高度,或者直接返回固定高度
 
 @return cell的高度
 */
- (CGFloat)cellHeight;


/**
 返回cell的复用id
 
 @return cell的复用id
 */
+ (NSString *)identifier;


/**
 注册cell

 @param table 要注册到的table view
 */
+ (void)registerFor:(UITableView *)table;

@end

Section类说明

@interface YTTableViewSection : NSObject

/**
 用来标识section的类型,要保证每个section的都不同
 代理方法里面如果要做特殊处理会用到,所以不能相同
 */
@property (nonatomic, copy) NSString *sectionKey;


/**
 section 里面 row 的 view model 集合
 */
@property (nonatomic, copy) NSArray *viewModels;


/**
 返回这个section有多少row,这个不用设置,在设置viewModels时,会自动设置
 */
@property (nonatomic, readonly) NSInteger numberOfRows;


/**
 是否自动添加分隔线
 */
@property (nonatomic) BOOL autoSeparator;
// 分隔线颜色 默认:#E6E6E6
@property (nonatomic, strong) UIColor *separatorColor;
@property (nonatomic, strong) UIColor *separatorBackgroundColor;
// 分隔线左边缩进
@property (nonatomic) CGFloat separatorLeftInset;
// 分隔线右边缩进
@property (nonatomic) CGFloat separatorRightInset;
// 分隔线的高度 默认1px
@property (nonatomic) CGFloat separatorHeight;

// section头部分隔线 不受separatorInset影响
@property (nonatomic) BOOL sectionTopSeparator;
@property (nonatomic) CGFloat topSeparatorHeight;
@property (nonatomic, strong) UIColor *topSeparatorColor;

// section尾部分隔线 不受separatorInset影响
@property (nonatomic) BOOL sectionBottomSeparator;
@property (nonatomic) CGFloat bottomSeparatorHeight;
@property (nonatomic, strong) UIColor *bottomSeparatorColor;

- (instancetype)initWithSectionKey:(NSString *)key viewModels:(NSArray *)viewModels;

Cocoapods支持

如果觉得可以就给个Star。 Github Repo

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏一“技”之长

从AFNetworking源码分析到应用全解 原

    AFNetworking是iOS/OS开发中常用的一个第三方网络库,可以说它是目前最流行的网络库,但其代码结构其实并不复杂,也可以说非常简洁优美。在AF...

74930
来自专栏DannyHoo的专栏

SDWebImage\ASIHttpRequest是第三方库

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010105969/article/details/...

11630
来自专栏清墨_iOS分享

iOS多个网络请求完成后执行下一步

在开发中,我们很容易遇到这样的需求,需要我们同时做多个网络请求,所有网络请求都完成后才能进行下一步的操作。如下载多个图片,下载完了才能展示。 今天我们就来研究一...

59670
来自专栏哈雷彗星撞地球

iOS下JS与OC互相调用(一)--UIWebView 拦截URL

最近准备把之前用UIWebView实现的JS与原生相互调用功能,用WKWebView来替换。顺便搜索整理了一下JS 与OC 交互的方式,非常之多啊。目前我已知的...

27540
来自专栏xx_Cc的学习总结专栏

iOS-控制器View的创建和生命周期

36160
来自专栏学海无涯

iOS开发之NSURLSessionUploadTask上传数据

苹果在 iOS9 之后已经废弃了NSURLConnection,NSURLSession成为其替代者,其基本知识网上很多,主要可以从NSURLSessionDa...

350100
来自专栏娱乐心理测试

iOS 如何把图片资源打包成bundle文件及遇到的坑(详解)

(1.)"Base SDK" 设置为 "Latest iOS (iOS 11.2)" (Xcode 9.2为例)

38020
来自专栏一“技”之长

SDWebImage源码分析 原

     SDWebImage是iOS开发中非常流行的一个网络图片加载库,如果你观察其源码,会发现其中的文件非常多,虽然文件数很多,但是作者的代码结构和条理却是...

31230
来自专栏小蠢驴iOS专题

手把手教你使用Bugly收集线上崩溃信息

1.5K30
来自专栏Rindew的iOS技术分享

iOS初步集成极光推送后你还要做这些事

38950

扫码关注云+社区

领取腾讯云代金券