iOS MVVM 处理初始视图状态
Posted
技术标签:
【中文标题】iOS MVVM 处理初始视图状态【英文标题】:iOS MVVM handling initial view state 【发布时间】:2018-09-21 04:43:50 【问题描述】:我正在尝试在 Objective C 中使用没有 Rx 的 MVVM,基本上类似于 MVP。我有一些非常基本的疑问想要解决
1.) 如何在视图中加载初始视图状态,基于配置。即当 UI 组件的初始状态可以根据某些配置值更改时。例如。视图中的按钮最初可以根据全局配置启用/禁用/隐藏。在一个视图中可能有很多 UI 组件的情况下,应该如何呈现这个初始视图状态?
视图模型是否应该将此配置(或视图状态对象)传递给视图并由视图决定如何呈现自己?或 视图模型是否应该将每个 UI 元素的状态传递给视图? 在 Rx 的情况下,VM 是否应该有一个视图状态属性或每个 UI 组件的状态属性?2.) 如何处理各个 UI 组件的状态?
VM 是否应该通过 enableButton1、hideTextView 等方法要求视图更新其视图状态或 它应该只是将“事件”或数据传递给视图,并让视图决定如何对这些事件做出反应。 在 Rx 世界中,视图应该与单个状态属性绑定还是仅与事件属性绑定?3.) 我很困惑谁应该触发某些操作,例如,让我们说“验证”。例如,在登录屏幕中,谁应该触发电子邮件/密码值的验证?
应查看要求 VM 验证,然后要求执行登录过程或 是否应该仅通过电子邮件/密码值将单击操作传递给 VM,然后由 VM 决定是否进行验证以及验证通过或失败时如何处理?【问题讨论】:
【参考方案1】:哇,这个问题包含了很多问题......让我们看看我能梳理出什么:
在一个视图中可能有很多 UI 组件的情况下,这个初始视图状态应该如何呈现?
当不使用响应式系统时,无论是在 Objective-C 还是 Swift 中,我的视图控制器最终都会得到一个在 viewDidLoad
中调用的 configureWithViewModel:
(Obj-C) 或 configure(viewModel:)
(swift) 函数。视图模型更改的时间。调用configure方法时,会在viewDidLoad中渲染初始状态。
视图模型是否应该将此配置(或视图状态对象)传递给视图并由视图决定如何呈现自己? View 模型是否应该将每个 UI 元素的状态传递给视图?
视图决定如何呈现自己,viewModel决定应该是什么值。 viewModel 只处理动态的视图部分。因此,例如,如果 UILabel 中唯一不同的是文本,那么 viewModel 会为文本提供一个字符串。如果 UILabel 也更改了 textColor,那么 viewModel 会同时提供 String 和 UIColor。
在 Rx 的情况下,VM 应该有一个视图状态属性还是每个 UI 组件的状态属性?
就个人而言,我为 viewModel 的每个动态视图提供了一个单独的 Observable,但在非 Rx 上下文中,我觉得这太复杂了,并且只有一个 update
可以同时提供所有状态。
如何处理各个 UI 组件的状态?
VM 是否应该通过 enableButton1、hideTextView 等方法要求视图更新其视图状态或 它应该只是将“事件”或数据传递给视图,并让视图决定如何对这些事件做出反应。
通过数据。观点并没有决定。例如 UIButton
有一个 isEnabled
属性。本例中的数据显然是Bool
。 viewModel 提供了 Bool,而 ViewController 只是将该 bool 分配给 View(或者 View 将其分配给自己。)
在 Rx 世界中,视图应该与单个状态属性绑定还是仅与事件属性绑定?
状态属性。类似:
viewModel.isMyButtonEabled
.bind(to: myButton.rx.isEnabled)
我很困惑谁应该触发某些操作,例如,让我们说“验证”。例如,在登录屏幕中,谁应该触发电子邮件/密码值的验证?
上面的措辞有点混乱。没有什么“触发操作”。当输入某些内容时,视图的输入部分会通知视图模型,并且视图模型要么忽略该输入,要么更新其状态。如果它更新其状态,那么它将更新发送到视图的输出部分。因此,以验证为例,您可以执行以下两项操作之一:
当用户点击“发送”按钮时,视图模型会收到电子邮件和密码。它负责做什么,并根据这些字符串的值更改其状态。然后它通知视图控制器它的状态已经改变。
当用户在每个文本字段中输入数据时,甚至可能是每个单独的字符,视图模型都会收到当前文本字段的值。它负责做什么,并根据这些字符串的值更改其状态。然后它通知视图控制器它的状态已经改变。
应查看要求 VM 验证,然后要求执行登录过程或 是否应该仅通过电子邮件/密码值将单击操作传递给 VM,然后由 VM 决定是否进行验证以及验证通过或失败时如何处理?
后者。我们的想法是将尽可能多的工作移出视图控制器,以便更容易控制/测试。
【讨论】:
感谢您回答这个巨大的问题。我几乎同意你的所有观点,我的思考过程也倾向于这一点。我有一个问题,但是当 VM 必须为 UI 表示状态提供数据时,例如 buttonText、buttonColor(状态的 3 种颜色)等。如果复杂的 UI 具有许多 UI 元素和状态,我们不会过多地污染 VM 吗?我们不是让 VM 在特定类型的视图下工作吗?如果 UI 发生变化,我们也必须更改 VM。虚拟机是否应该始终针对特定视图,我知道根据定义它是但是.. ViewModel 是将逻辑与效果分离;这不是关于隔离变化。编写良好的视图模型将允许您测试您的逻辑 在屏幕上显示任何内容、进行网络调用或保存/读取存储/从存储中读取。它会将您的视图控制器变成humble object以上是关于iOS MVVM 处理初始视图状态的主要内容,如果未能解决你的问题,请参考以下文章
ios MVVM实践 刷新网络请求+tableView展示数据