SwiftUI - 如何将 EnvironmentObject 传递到视图模型中?

9 浏览
0 Comments

SwiftUI - 如何将 EnvironmentObject 传递到视图模型中?

我想创建一个EnvironmentObject,可以被View Model(不仅仅是View)访问。

环境对象可以跟踪应用程序会话数据,例如登录、访问令牌等,这些数据将传递到View Models(或需要的服务类)中,以允许调用API从这些EnvironmentObjects传递数据。

我尝试从View向ViewModel类的初始化程序中传递会话对象,但是遇到了错误。

如何使用SwiftUI访问/传递EnvironmentObject到View Model中?

admin 更改状态以发布 2023年5月21日
0
0 Comments

你不应该这么做。使用MVVM是SwiftUI最佳实践的一种常见误解。在SwiftUI中,MVVM没有任何用处。你正在问是否可以把一个矩形塞进一个三角形形状中,它是无法完全契合的。

让我们从一些事实入手,一步一步地进行处理:

  1. ViewModel是MVVM中的模型。

  2. MVVM没有考虑值类型(例如;在Java中没有这样的东西)。

  3. 没有状态的值类型模型(没有状态的模型)在不可变性方面被认为是比有状态的引用类型模型更安全的。

现在,MVVM要求您以这样的方式设置模型,以便每当它更改时,它以某种预定方式更新视图。这就是所谓的绑定。

如果没有绑定,您将无法实现良好的关注点分离,例如;将模型和相关状态拆分并与视图分开保留。

这是大多数iOS MVVM开发人员失败的两个方面:

  1. iOS没有传统Java方式的“绑定”机制。一些人会忽略绑定,认为调用一个名为ViewModel的对象可以自动解决一切;一些人则会引入基于KVO的Rx,并在MVVM本应使事情变得简单时使一切变得更加复杂。

  2. 有状态的模型对于开发人员来说太危险了,因为MVVM过于强调ViewModel,过于淡化控制的状态管理和一般管理纪律;大多数开发人员最终会认为可用于更新视图的有状态模型是可重用且可测试的。这就是Swift最初引入值类型的原因;一种没有状态的模型。

现在回到你的问题:你问是否可以让你的ViewModel访问EnvironmentObject(EO)?

你不应该这么做。因为在SwiftUI中,符合View的模型自动具有对EO的引用。例如;

struct Model: View {
    @EnvironmentObject state: State
    // automatic binding in body
    var body: some View {...}
}

我希望人们能够欣赏SDK被设计得多么紧凑。

在SwiftUI中,MVVM是自动执行的。不需要手动绑定到视图的单独ViewModel对象,并需要通过引用传递EO。

上述代码是MVVM。例如;具有对视图的绑定的模型。但是,由于该模型是值类型,因此您可以将控件拆分重构为控制(例如,在协议扩展中)而不是将模型和状态拆分为视图模型。

这是官方SDK将设计模式适应到语言特性中,而不是仅强制实施它。实质胜于形式。看看你的解决方案,你必须使用单例,这基本上是全局的。您应该知道访问全局的危险性,因为您必须使用引用类型模型,而这份代码缺乏不可变性的保护!

TL;DR

在SwiftUI中,不要像Java那样使用MVVM。使用Swift-y的方法进行操作,它已经内置在其中。

希望更多的开发人员能看到这一点,因为这似乎是一个常见的问题。

0
0 Comments

你可以这样做:

struct YourView: View {
  @EnvironmentObject var settings: UserSettings
  @ObservedObject var viewModel = YourViewModel()
  var body: some View {
    VStack {
      Text("Hello")
    }
    .onAppear {
      self.viewModel.setup(self.settings)
    }
  }
}

对于ViewModel:

class YourViewModel: ObservableObject {
  var settings: UserSettings?
  func setup(_ settings: UserSettings) {  
    self.settings = settings
  }
}

0