最近将自己做的项目进行组件化,恶补了很多关于组件化的知识。最终采用方案是CASA大大的iOS应用架构谈 组件化方案。但是在具体实施的时候,关于TableView的组件化遇到了很大的问题。

通常TableView的Cell会来自不同的组件,那么该如何交付Cell?

工程通常是采用MVC或者MVVM的,交付出Cell意味着也要将ViewModel拔出萝卜带出泥的全拉出来!其实不止是Cell,原则上讲,这其实涉及到所有的View的交付。关于这个事情咨询过CASA大大,给出的答复是

我的设计里面没有model。我也不主张在设计里面引入model,包括view model这种定义很暧昧的“model”。你提到的问题就是不采用去model化设计会遇到的典型问题之一。

这就很尴尬了,因为无论是历史遗留原因也好,还是模块开发人员的习惯也好,很难保证项目里完全采用去model化。本文主要是探讨在model化的设计下,如何做好解耦(这里暂时只探讨TableView)。

总体思路是,以Section为单位分而治之。

大家都知道UITableView虽然有Section的概念,但是实际上是没有Section的实例的,只是在indexPath中加了一个标记罢了。
在这里,我将section这个概念进行具体化,每个Section管理自己Section中的Cell,这其中包含了Cell与ViewModel建立对应关系、以及Cell的个数,甚至包含Cell被点击之后响应的预备工作(如果是Cell内部有view要响应点击,那响应工作是在Section中进行,如果是Cell自身要响应点击,那么就做好准备工作,譬如装填好要跳转的UIViewController的实例)。抽象出一个BaseSection来定义各种行为(定义一个刷新的方法以调起对应的网络请求),然后各个组件进行子类化来达到自定义的目的。

对于组件使用方而言(就是壳工程中的TableView),每个Section有点Self-Manager(iOS 开发中的 Self-Manager 模式)的味道。也有点类似于每一个Section都是一个SubViewController,当然,由于TableView并不知道Controller是谁,所以Section也肯定不会知道,Section只会做交付工作,而跳转之类的逻辑还是交由组件的使用方负责,这样使用方就更像是搭积木,想Push还是Present随你.Section实质上是一个弱化了上下文(不知道Controller是谁)的Manager。

组件的使用方只需跟组件要来一个Section(当然,使用方并不需要知道具体是什么,只要是个Section就行了,交付的类型是个BaseSection),然后在需要的时候(譬如要展示了)扔给TableView即可。这样每个Section散落在各个组件内,组件的使用方拿这它们即可找TableView兑换出想要的东西。

Demo暂时先不放了,先在项目中实践一段时间,待成熟稳定之后再扔出来。
经过几个月的测试,使用已基本稳定,轮子在此YLTableView

同时看到CASA大大更新了博客,提出了利用Mediator来实现TableView的组件化,也是一个非常不错的思路。我这里的思路与其有很大区别,这里是以一个通用的方式将TableView进行封装,而不需要每次都针对TableView在Mediaor中进行处理。

Preference

  1. iOS应用架构谈 组件化方案
  2. iOS 开发中的 Self-Manager 模式