MVVM 编程最佳实践

编程入门 行业动态 更新时间:2024-10-08 13:37:42

<a href=https://www.elefans.com/category/jswz/34/1768191.html style=MVVM 编程最佳实践"/>

MVVM 编程最佳实践

MVVM 由 MVC 演进而来,关于与 MVC 架构职责重叠的部分,这里不再赘述,本文简单介绍一下 MVVM 中需要注意的点。

MVVM 简介

在介绍 MVVM 架构之前,我们先来了解一下 iOS App 中两个重要的、不可或缺的部分 UI 逻辑和业务逻辑:

  • UI 逻辑是指把原始数据加工成最终展示数据的逻辑,包括原始数据的格式化加工处理,数据的请求发起与响应,处理来自 UI 的交互活动及更新原始数据等。
  • 业务逻辑是处理原始数据到最终用户界面之间通信的底层过程,包括从持久化存储中(如 db 或 文件)或者网络中获取解析原始数据,提供操作数据的接口,处理状态记录与变更的逻辑等。

MVVM (Model-View-ViewModel) 是一种设计模式,源自 MVC 模式,它涉及一个称为 ViewModel视图模型 的新概念,解决了之前 MV (X) 模式庞大的问题。下面是 MVVM 的架构:

在 MVVM 设计模式中,View 和 ViewController 紧密耦合在一起,并被视为一个组件,它也包括它们的 .xib 和 .storyboard 文件。

在 MVC 架构中,ViewController 因网络、处理来自 UI 的信号、收集响应等活动而变得庞大甚至超载,MVVM 引入了 ViewModel 这个新组件划分和委托了 ViewController 的职责。

我们来看看 MVVM 架构中各个组件的职责:

  • Model 模型 – 与 MVC 设计模式中的职责相同,用来表征 App 的数据并封装操作数据的接口,负责业务逻辑处理,它由 ViewModel 持有加工使用,并在 ViewModel 发送数据更新信号时更新自身。
  • View (ViewController) 视图(视图控制器) – 表征用户界面的视觉元素,负责设置 UI 视图以及处理用户交互。View 和 Model 之间没有直接交互,它应该通过 ViewModel 绑定并以最终展示的格式请求它需要的内容。ViewController 只负责更新视图并将视图的信息传递给 ViewModel。
  • ViewModel 视图模型 – 负责所有的 UI 逻辑,包括格式化模型数据以供视图控制器显示、将模型输出传递给视图控制器 以及 获取视图输入并更新模型。它完全独立于 ViewController,从 ViewController 接收信息,处理所有这些信息并将结果发送回 ViewController。

MVVM 的最终目标是将 ViewController 中的 UI 逻辑隔离到 ViewModel。此外,ViewModel 中还可能隐藏了用于视图呈现的数据准备代码、异步网络调用代码以及用于模型更新的监听代码。当 ViewModel 需要与 View 进行任何通信时,它将通过数据绑定来完成。

MVVM 相比 MVC 最大的改进是将获取和加工数据逻辑从 ViewController 移动到 ViewModel,ViewController 的职责是仅显示 UI 并从 UI 获取详细信息。同样,ViewModel 也不需要关心 ViewController 是从哪里以及如何获取数据的,它唯一关心的是如何处理数据。因此,所有职责都是隔离的,确保每个组件都相互独立。

iOS 数据绑定的方法

在 MVVM 中,需要一种将 ViewModel 的输出绑定到 View 的方法,有几种方法可以进行此类绑定:

  • KVO:通过 iOS 观察者模式实现属性变化的监听。
  • FRP 函数式响应式编程:一种将事件和数据作为流 stream 处理的范例。对于 Swift 语言,Apple 的新 Combine 框架就采用了 FRP,RxSwift 和 ReactiveSwift 是 FRP 的两个流行框架。
  • Delegate 委托:使用委托方法在值更改时传递通知。
    Block:通过 block 或闭包的方式在值发生变化时回调通知。
  • Swift Box 装箱:使用属性观察者通知观察者一个值已经改变。

ViewModel 的职责

  1. 纯粹的 MVVM 架构中,根 viewModel 通常在 AppDelegate 中生成,其它所有的子 viewModel 由根对象的依赖关系图逐步生成,由于我们在对象解耦方面还未引入相关设计模式,采用按需方式在实际使用的地方各自生成。因此,我们的 viewModel 初始化在 ViewController 中生成,也可以通过属性传参给当前
  2. ViewController 持有的 viewModel 赋值
    纯粹的 MVVM 架构中,应该做到 dataModel 不对外暴露。但我们的业务中 dataModel 与 view 的耦合还比较重,短期内无法做到这点,因此,我们的要求是 viewModel 尽量不要暴露原始 dataModel。
  3. viewModel 被 view 层持有,并绑定 view,以实现获取数据后自动更新 UI。我们目前使用 MVVM 还未引入三方绑定框架,而是通过 block 回调的形式完成数据流的单向通知。
  4. viewModel 不能任意包含 View 层的代码(包括ViewController 和 UIView 及其子类);特殊情况:如果 model 层的接口返回 View,则暂时可以保持原状
    controller 持有 viewModel,viewModel 持有原始 dataModel,viewModel 还可以包含 子 viewModel,用来管理复杂界面的逻辑,子 viewModel 通常在父 viewModel 中生成
  5. viewModel 层的代码主要包含:view层的事件处理、网络请求、原始数据(dataModel)加工代码、导航跳转逻辑(暂不实现)
  6. 当 viewModel 的代码量过于庞大时,需要对 viewModel 里面的业务进一步拆分职责

MVVM 的优缺点

MVVM 是一种优秀的设计模式,无论我们使用何种编程语言,它都可以减少 View 层的代码量并保持代码清洁、可重用、可维护和可测试,从而提供高质量的代码,它的优点如下:

  • 控制器复杂性降低 —— VVM 通过从 ViewController 中移出大量业务到 ViewModel 而l来辑来简化 ViewController。
  • 可测试性增强——众所周知,ViewController 由于与 View 关系紧密而难以测试,通过将数据操作移至 ViewModel,MVVM 使测试变得更加容易。我们最终可以测试业务逻辑,而不必担心 View 实现。
  • 关注点分离——ViewModel 为 ViewController 提供透明接口用于与 Model 层和 View 层进行交互,各层之间的通信更透明,View Model 也能够更好地表达 View 加工的逻辑,从而与具体业务逻辑分离。

任何一种设计模式都有其优缺点,MVVM 也不例外:

  • 引入额外的组件:MVVM 引入了额外的 ViewModel 对象,如果没有很好的理解和使用 MVVM,这个 ViewModel 有可能变成另一个 Massive ViewModel,从而回到 MVC 甚至更糟。
  • 绑定机制: MVVM 需要某种数据绑定方式来实现 View 和 Model 通信的解耦。
  • 内存:持有 ViewModel 时,必须注意内存管理和对象的生命周期。

参考

Clean Architecture and MVVM on iOS
Template iOS App using Clean Architecture and MVVM

更多推荐

MVVM 编程最佳实践

本文发布于:2024-02-14 09:17:49,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1762876.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:MVVM

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!