gpt4 book ai didi

swift - RxSwift、ViewModels 和 UI 绑定(bind)

转载 作者:行者123 更新时间:2023-11-28 07:49:56 25 4
gpt4 key购买 nike

我想知道在以下情况下最佳做法是什么:

  • 项目设置是模型- View - View 模型
  • 我需要显示一个带有文本字段的屏幕(例如 name ),用户可以在其中编辑特定 Model 的详细信息
  • ViewModel 包含一个 Observable<Model> ; ViewModel 负责从 API 中检索数据
  • View 包含需要使用 Model 中的当前数据预先填充的输入字段
  • 输入字段需要绑定(bind)到例如BehaviorRelay ViewModel 中的 s

我正在努力寻找解决这个问题的最佳方法:

  • 我不想在 ViewModel 中订阅
  • 我希望 ViewModel 负责检索数据并填充 BehaviorRelay s 或类似

我基本上想要类似于 BehaviorRelay 的东西s,但初始值来自 Observable .在订阅(绑定(bind))BehaviorRelays 后,我希望它们从 API 检索数据。或者 flatMap一个ObservableBehaviorRelay

解决这个问题的最佳方法是什么?

我以前实现它的方法及其缺点:

  1. 跳过 BehaviorRelay s 在 ViewModel 中,并将状态保存在 ViewController 中。只需从 ViewController 订阅 Observable<Model>在 ViewModel 中并将其绑定(bind)到 UI。然后,当用户想要保存数据时,从 UI ( withLatestFrom() ) 检索最新值并将其作为值传递给 func save(attribute: Value)。在 View 模型中。这可行,但我想将所有状态(和业务逻辑)保留在 ViewModel 中。
  2. 在 ViewModel 中,使用 BehaviorRelay初始值为空,然后在 init()的 ViewModel,检索数据并将其绑定(bind)到 BehaviorRelay秒。这意味着在 ViewModel 中有一个订阅,我想避免这种情况。
  3. 有类似 func refresh() -> Completable 的东西在 ViewModel 中,它在 BehaviorRelay 中设置值s 在其 do(onNext:) .这行得通,但感觉很老套。
  4. 有一个 let refresh = PublishSubject<()>()在 ViewModel 中,例如

    var model: Observable<Model> {
    refresh
    .startWith(())
    .flatMapLatest { retrieveData() }
    }

    再次使用 do(onNext:) .与以前的解决方案相同的缺点(感觉很老套)。

  5. 在初始化 ViewModel 之前检索数据,并使用模型实例初始化 ViewModel。我不喜欢这个解决方案,因为我希望 ViewModel 负责检索它自己的数据。

还有别的办法吗?

最佳答案

我的第一点是,我认为您需要多考虑一下 ViewModel 在 MVVM 中的作用。 viewmodel 的目的是转换/修改模型中的数据,使其非常适合在那个屏幕上显示。因此,如果您正在制作一个充满可编辑字段的屏幕,那么 ViewModel 应该将数据拆分为那些离散的字段。在 Rx 中,这通常意味着为每个字段公开一个 Observable(如果需要,也可以是 Driver)。目标是使 View 模型中每个属性的绑定(bind)简单。 View 不应执行属于 VM 的任何表示转换/逻辑。

您的 VM 不应进行任何订阅是正确的,ViewController(MVVM 中的 View )将对它显示的每个字段进行订阅。您可以让 View 模型在调用 API 时使用 .share() 并使用生成的可观察对象来提供每个字段可观察对象,这样它们就不会各自调用 API View 订阅它们。

我不确定您所说的需要 BehaviorRelay 指的是什么。也许你可以澄清那里的需求。如果是因为您想要一种触发刷新的方法,那么您的第 4 个项目符号就很有意义。你可以这样设置

让 fetchDataTrigger = PublishRelay();

let dataModelObservable = fetchDataTrigger.asObservable()
.startWith(())
.flatMap {
return goCallMyApi()
}
.share()

然后您的每个属性都可以转换 dataModelObservable 的输出以生成该字段的值。如果您想触发刷新,您只需调用 fetchDataTrigger.accept(()) 来响应您的按钮按下或任何触发刷新的操作。

关于swift - RxSwift、ViewModels 和 UI 绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49999237/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com