MVVM 框架结构

MVVM 框架结构

MVC是经典的分层结构,Model 层 和 View 层不直接通信

Controller 层 调用网络请求,

当消息响应后,将返回的结果 变为 model 化的数据源 DataSource

然后Controller层将DataSource 传递给 View

View 拿到数据后 会根据 DataSource 进行 处理,展示界面

这是经典的数据请求到展示的过程。

iOS 中,最常使用的是UITablview 和UICollectionView ,每个Tablview 或者CollectionView

都包含了多组 小的cell 模型, 当创建这两种类型的视图时,

需要告诉视图,有几组,每组有几行,每行的行高是多少,每个行是哪种类型的,

每个行中,具体的样子是什么样子的,这些内容UITablview和UICollectionView

都提供了多个代理方法来实现,

一个Controller 需要添加Tablview 或者CollectionView 时,不得不加上大量的代理,

每次创建一个界面都要写很多的代理内容,使得Controller 重复内容过多, 造成臃肿

不容易找到 真正需要的代码。

一个简单的解决方式 是提供一个 TableView 的基类Controller 和一个CollectionView 的基类Controller

然后把所有的数据都存到一个双层的数组 数据源DataSource 中,

所有的代理方法都会根据 DataSource 来进行处理

比如

有多少组 就是 DataSource.count

某一组多少行 [DataSource indexPath.section ].count

每行中的Cell的数据源 也就是具体的实际内容
model = [DataSource indexPath.section ][indexPath.row]

写一个基类的Cell 基类的Cell 添加一个 id 类型的model ,这样就可以进行统一传递

每个子类的cell 都重写 setModel:(id)model 的方法,这样 就可以接收到model,

这种方式很好用,子Controller 只需要选择继承 Tablview 或者CollectionView 的控制器

就可以免去写代理的痛苦,只用管好数据源,子类需要的代理方法,就重写 也就完事了。

基本上一个页面全部完成,可以控制在200 行以内。

这种方式的弊端也很明显,就是必须要继承 Controller 。

如果要使用一个Tablview ,必须使用这个Controller ,不是一个太好的模式。

因为这个基类Controller ,不包含项目中业务的处理,

比如TabBar 的隐藏显示。导航栏的返回样式统一控制

这些内容是在项目中的基类Controller里面的。

当你继承TableView 的Controller 时,就不能继承项目中的基类Controller 了。

当然你可以说 ,让 TablView 继承 项目中的基类Controller 不就好了吗,

这样做 不是 不行,本质上 还是在TablView Controller 中 把 基类很多方法又重新写了一遍。

一方面冗余,另一方面 就是 我们在做基础类也好 ,抽象类也好,都要保证其 复用性 和功能唯一性。

这样的写法,每次换一个基类控制器,都要重新改写继承,复用性不好。TableView 多了 基类控制器

的功能,唯一性不好。

所以上述的方案 在处理 简单 不经常变化的业务上 是可以实现的。

那么这个方案不足 ,又有什么方案来解决这个问题呢?

想到 我们在封装一个自定义的功能界面时,我们都是将View 抽出,

然后在Controller 中import View 模块,这样就免去了 继承的痛苦,

和View 有关的逻辑部分 都 和View 写在一起。需要外部处理的 数据源

都会以代理的形式放出来 就像Tablview的代理一样的

这种思路是不错,非数据源部分都交给 View处理, 但是也会带来另外一个

问题 View 会变得臃肿。 我们知道代码不写在Controller 里面,就要写在

其他地方。把逻辑写在View 里面,方法存疑。

还有就是苹果的Tablview 已经把除了 交给代理的操作 全部完成了。

基本不能再简代码量了。

我在看MVVM 时,想了很久 这个ViewModel 到底代表的是什么呢?

每个人对这个都有着不同的理解,

在这里,我认为 ViewModel 就是对 DataSource 的进一步管理。

比如说 Tablview ,我在Tablview 的基类Controller 中将所有代理方法都统一处理了

现在我创建一个 TablView 的 TableViewModel,

来接管 Controller 中的TablelView 和Controller 中的DataSource

TableViewModel 中不把TablView 变成全局对象,只是TablView他的代理方法。

因为TablView每个代理方法都会回传TablView本身,自然不需要变成全局对象。

DataSource 需要变成全局对象,来填写 代理方法中的具体内容。

这样的话,就不再需要 Tablview 的基类Controller 了,只需抽一个TableViewModel的基类

需要在Controller 中 添加一个 TablView 的时候

只需要写一个TablView 的懒加载

然后import TableViewModel的基类 ,把DataSource 和 Tableview 托管给TableViewModel

就行了,多了一个tablveviewmodel 层,但是把整个层次划分开了。

也不必担心 不能继承项目中基类控制器的问题了。

自此,我对ViewModel 的理解就出来了

管理View 但不持有View 持有DataSource ,来管理View 的代理方法,统一业务,将真正需要处理的业务
再转发给Controller 去管理
ViewModel 只关心 DataSource,不关心View 自身

按照这种逻辑,我将延时获取数据(网络请求,或者本地读取)数据源的部分也抽离出来。
给Controller 增加一个VCViewModel,并成为代理

Controller 懒加载VCViewModel 并loadDaTa 当 数据获取并转换为model 的DataSource 后
回传给 Controller

Controller 会将DataSource 接收并 转交给TablViewModel 接管 然后 TablView reloadData

这样网络请求也分离了, 不需要再Controller 中写大段的 网络请求了

Controller 中 也就 只剩下了 初始化 ,某些跳转代理。数据已加载代理,和一些特殊的处理了。

这样对组件的分离也变得容易许多,

然后我按照这种思路 也拆开了CollectionView 的ViewModel

实际上 每个Cell 也是view 当然也需要一个 Cell 的ViewModel 用来管理cell 的各种变化以及model

总的来说 就是每个view 都应该有个ViewModel 去管理它,ViewModel 相当于一个数据流的管理器

而不应该局限他的名字的作用范围。

猜你喜欢

转载自blog.csdn.net/github_35041937/article/details/78195066