iOS MVVM 与 RxSwift:viewmodel 无处不在的缺点是什么?
iOS MVVM with RxSwft: what is the drawback with viewmodel everywhere?
RxSwft 非常适合iOS MVVM。
随处放置viewmodel,违背得墨忒耳法则(最少知识原则)。
其他缺点是什么?
会不会导致内存泄露?
举个例子:
ViewController 有一个 viewModel
ViewModel 有一些事件信号,比如下面的返回事件
class ViewModel{
let backSubject = PublishSubject<String>()
}
ViewController 有 contentView
和 viewModel
,contentView
初始化有 viewModel
lazy var contentView: ContentView = {
let view = ContentView(viewModel)
view.backgroundColor = .clear
return view
}()
和 ViewModel 的各种主题在 viewController 中订阅以处理其他部分视图
viewController
是调度中心。
ViewModel
是事件中转站。 ViewModel
无处不在,在Controller中,在View中,收集不同的事件触发器。
代码很杂乱
在 ContentView
中,用户点击 rx 事件,绑定到 viewController
中的 viewModel
tapAction.bind(to: viewModel.backSubject).disposed(by: rx.disposeBag)
用户事件很容易连接起来。
但实际上存在内存泄漏
那么其他缺点是什么?
你是对的,有一些缺点,如果你只想要一个数据绑定,我建议使用 Combine
代替,因为不需要第 3 方库,你已经有了它。 RxSwift
当您将它用作语言的一部分时,它是一个非常强大的工具,而不仅仅是用于数据绑定。
根据我使用 RxSwift
的经验提出的一些建议:
- 尝试将 VM 作为结构,而不是 类。
- 避免在您的 VM 中使用 DisposeBag,而是让 VC 订阅所有内容(更好地避免内存泄漏)。
- 为子视图、单元格、子视图创建自己的 VM VC,而不是共享的。
因为你的 VC 是一个调度中心,我会为你的内容视图制作一个单独的虚拟机,并在 ContentView
VM
和 ViewController
VM
通过你的控制器。
ViewModel 没有违反 Demeter 法则,但它确实违反了单一职责原则。解决这个问题的方法是使用多个视图模型,每个功能一个,而不是整个屏幕使用一个视图模型。这将使视图模型更具可重用性和可组合性。
如果您将视图模型设置为单个函数,将多个 Observable 作为输入并 returns 单个 Observable,您还将消除任何内存泄漏的可能性。
例如:
func textFieldsFilled(fields: [Observable<String?>]) -> Observable<Bool> {
Observable.combineLatest(fields)
.map { [=10=].allSatisfy { !([=10=] ?? "").isEmpty } }
}
您可以将以上内容附加到您想要根据是否已填写所有文本字段启用按钮的任何场景。
您满足 SRP,并且由于对象分配是自动处理的,因此无需担心上述会泄漏内存。
RxSwft 非常适合iOS MVVM。
随处放置viewmodel,违背得墨忒耳法则(最少知识原则)。
其他缺点是什么?
会不会导致内存泄露?
举个例子:
ViewController 有一个 viewModel
ViewModel 有一些事件信号,比如下面的返回事件
class ViewModel{
let backSubject = PublishSubject<String>()
}
ViewController 有 contentView
和 viewModel
,contentView
初始化有 viewModel
lazy var contentView: ContentView = {
let view = ContentView(viewModel)
view.backgroundColor = .clear
return view
}()
和 ViewModel 的各种主题在 viewController 中订阅以处理其他部分视图
viewController
是调度中心。
ViewModel
是事件中转站。 ViewModel
无处不在,在Controller中,在View中,收集不同的事件触发器。
代码很杂乱
在 ContentView
中,用户点击 rx 事件,绑定到 viewController
tapAction.bind(to: viewModel.backSubject).disposed(by: rx.disposeBag)
用户事件很容易连接起来。
但实际上存在内存泄漏
那么其他缺点是什么?
你是对的,有一些缺点,如果你只想要一个数据绑定,我建议使用 Combine
代替,因为不需要第 3 方库,你已经有了它。 RxSwift
当您将它用作语言的一部分时,它是一个非常强大的工具,而不仅仅是用于数据绑定。
根据我使用 RxSwift
的经验提出的一些建议:
- 尝试将 VM 作为结构,而不是 类。
- 避免在您的 VM 中使用 DisposeBag,而是让 VC 订阅所有内容(更好地避免内存泄漏)。
- 为子视图、单元格、子视图创建自己的 VM VC,而不是共享的。
因为你的 VC 是一个调度中心,我会为你的内容视图制作一个单独的虚拟机,并在 ContentView
VM
和 ViewController
VM
通过你的控制器。
ViewModel 没有违反 Demeter 法则,但它确实违反了单一职责原则。解决这个问题的方法是使用多个视图模型,每个功能一个,而不是整个屏幕使用一个视图模型。这将使视图模型更具可重用性和可组合性。
如果您将视图模型设置为单个函数,将多个 Observable 作为输入并 returns 单个 Observable,您还将消除任何内存泄漏的可能性。
例如:
func textFieldsFilled(fields: [Observable<String?>]) -> Observable<Bool> {
Observable.combineLatest(fields)
.map { [=10=].allSatisfy { !([=10=] ?? "").isEmpty } }
}
您可以将以上内容附加到您想要根据是否已填写所有文本字段启用按钮的任何场景。
您满足 SRP,并且由于对象分配是自动处理的,因此无需担心上述会泄漏内存。