带有RxSwift的MVVM

背景

在开发iOS应用程序时,您知道用于开发iOS应用程序的体系结构是MVC(模型-视图-控制器),每个应用程序组件按其职责分开。

在MVC架构上,模型负责提供数据或控制与数据访问有关的所有事物。 PersonPersonDataAccess类是模型的示例。 View负责将数据显示到用户界面。 并且,最后一个是Controller,负责更改模型并准备要呈现给View的数据。

根据Apple MVC的概念,视图将用户操作发送到控制器,然后控制器使用从视图发送的数据更新模型,然后模型将模型中的数据更改通知控制器,最后一个是控制器更新视图。

看起来很简单,对吧? 但是现实与上面的概念并不相同。 大多数iOS开发人员(包括me😂)倾向于制作Massive View Controller。

为什么将其视为问题?

因为视图和控制器紧密耦合,很难说它们是分开的。 在这种情况下, UIViewController子类被视为View。 因此,您倾向于将所有这些职责(网络调用,事件处理,数据更改,显示数据等)写入视图控制器( UIViewController子类)。

似乎易于实现,但有很多后果。

  1. 由于表示和数据操作合为一层,因此很难测试业务逻辑(视图)
  2. 难以维护
  3. 膨胀的UIViewController
  4. 继续…

由于以上所有这些问题,我开始学习一种替代的体系结构,该体系结构解决了这些问题。

认识MVVM

因此,这是视图控制器庞大性的拯救。 有一个名为ViewModel的组件。 那么,ViewModel的职责是什么?

就像MVC架构上的Controller一样,ViewModel负责更改模型并准备要呈现给视图的数据。 但是,有许多差异。 ViewModel提供了到View的数据绑定机制,因此,如果ViewModel上有数据更改,则View将自动更新,并且ViewModel没有对View的引用。

就个人而言,由于数据绑定机制,我喜欢这种体系结构,因此如果ViewModel发生更改,则View可以更新自身,并且由于职责分离,因此易于测试模型和业务逻辑。

因此,将MVVM应用于iOS开发的好处是

  1. 易于测试业务逻辑和模型
  2. 视图几乎是被动的,因为存在数据绑定,尽管如此,我们仍然使用视图控制器执行segue(作业,请分开此😂)
  3. 轻松更改UI而不弄乱业务逻辑
  4. 您可以将业务逻辑或网络调用放入ViewModel,这样视图控制器就变得不那么肿了

ViewModel的经验法则

  1. 无参考资料
  2. 没有import UIKit
  3. 没有引用任何UIKit的组件,例如UIViewUIButtonUITextField
  4. 只是一个数据。 JSON,字典或其他数据结构

RxSwift

ReactiveX提供的一种反应式编程框架。 这是Rx的Swift版本。 它依赖于可观察的模式,如果Observable发生了数据更改或事件,则观察者可以执行某些操作。 在这里可以找到RxSwift的更多详细信息。

在这里,我在MVVM体系结构上使用RxSwift提供从ViewModel到View的数据绑定,并在Model发生更改时通知ViewModel。

谈话很便宜,请告诉我代码!

您可以在此处访问我的github存储库,以更好地了解MVVM + RxSwift的实现。 我将解释该项目的重要课程

模型

说明:

  1. 上线nr。 7,我声明了一个名为todosFromCoreData的变量,ViewModel可以观察到。 并在线上nr。 在图8中, managedObjectContext变量是一个用于存储NSManagedObject对象(作为CoreData框架的一部分)的对象。
  2. 当有从该类实例化的对象时,初始化程序用于从核心数据中获取数据
  3. 数据操作,例如获取待办事项,添加待办事项,删除待办事项或更改待办事项。 更改数据后,我们必须从持久性存储中重新获取更新的数据。

视图模型

因此,在ViewModel中,我有3个成员:

  1. todos :用于将源绑定到视图
  2. todoDataAccessProvider :用于更改模型中的数据
  3. disposeBagdisposeBag一部分,用于内存管理。 在这里可以获得更多信息

方法fetchTodosAndUpdateObservableTodos()用于从TodoDataAccessProvider类中订阅可观察的TodoDataAccessProvider ,如果有更新,则todos将进行相应的更新。

第30–42行用于处理视图中的事件,例如添加待办事项,删除待办事项和切换待办事项。 我只是从todoDataAccessProvider调用方法来更改模型。

视图

在第nr行。 9,我有一个从TodoListViewModel实例化的成员,然后看一下viewDidLoad()方法。

上线nr。 18,调用populateTodoList()方法,该方法执行从ViewModel到View的绑定,然后将其呈现到UITableView

然后在行nr。 19,有一个调用setupTodoListWhenTableViewCellTapped()的调用,当通过反应性包装器将项目选择为表视图委托时,该调用将执行操作。 从todoListViewModel调用toggleTodoIsCompleted(withIndex:)

然后在行nr。 20,有一个对setupTodoListWhenTableViewCellDeleted()的调用,当通过反应性包装将项目删除到表视图委托时,该调用将执行操作。 从todoListViewModel调用removeTodo(withIndex:)

最后一个@IBOutlet buttonAddTodoTapped(_:)用于处理添加Todo的事件,并从todoListViewModel调用addTodo(withTodo:)

可测试性和结论

现在,View层不再那么肿胀,因为它具有对ViewModel的绑定机制,并且View只能观察ViewModel的更改。 现在,可以轻松测试ViewModel或Model😉

下一步是什么

希望您能在下一个项目中了解如何实现MVVM架构,如果有一些无法理解的内容,请在评论中告诉我。 干杯。