问题:在 TableView 中展示多种 model
开发日常,起初 tableView 只有一个中 model,tableView 展示 [ModelType] 数组,可是日子久了,这个 ModelType 的 type 你都不知道有多少种可能,每次都要加,对于 cell 的种类也会不停地加。
怎么解决这种多 modelType 在一个list中的问题呢?
方案可能性
提供中间层封装差异
(个人因为看了好久PATs,觉得像 Protocol,类继承,Any,enum…… 都属于类型擦除,提取抽象的过程中,抽象的部分就是要做擦除的过程,至于使用什么方式因具体场景而异)
中间层用啥?
- protocol
- class 继承
- Any
- 结构中包含具有差异 model——当做成员属性,modelType 也要用 1,2方式抽象下
- enum
各方案的分析
针对 1,2 —— protocol,class 继承
- 缺点a:把各种 ModelType 都有的属性再写一遍提取到中间层中
- 缺点b:有些 property 是 model 特有的,别的 model 没有(这时有的人可能也放在中间层中当做可选型)
- 缺点c:在 b 的前提下,这个中间层为了满足各个差异,不断地加property 而爆炸
针对 3 —— Any
- 缺点a:漫天遍地反射代码
- 缺点b:维护性差,同事之间改代码,迭代过程很痛苦
- 缺点c:model 数组发生变化的时候如果只是 reload 还好,可是如果想做局部刷新引入
DifferenceKit相关的库,怎么办 Any 不遵循 Equable
针对 4 —— 其实是删除了的,可略过,是为了引出 5 写的
protocol CaseType {}
struct ModelWrapper: CaseType {
var model: CaseType
}
觉得哪里怪怪的,相信很多人开发过程中都想过用这种方式做擦除,不过跟 1,2 的方式好像没啥差别…… 所以 4是在浪费时间
针对 5
swift 中 enum 几乎包含了所有 struct 特性,除了没有成员属性,很多情况
但是 swift 颠覆性提供了带有关联值 enum,这让 enum 带有了擦除类型的功能类似下面的代码。对于struct,enum 免费的提供了分类与层次结构编码的效果
// 带有关联值 enum,用 struct 表示有点类似这样的代码
protocol CaseType {}
struct ModelWrapper: CaseType {
var eraseData: CaseType
}
// 实际类表中,TableCell 的 model 层擦除
enum Cell {
case banner(BannerModel)
case square(User)
case rectange(Room)
……
}
Cell 不需要任何 ModelWrapper 的封装方式就可以擦除 model 的差异。也满足列表局部刷新 DifferenceKit
因为 enum 的特性,Cell 还可以穷尽各种类型
- 缺点:使用 if case 的方式读取关联值的写法不友好