SwiftUI - 如何将 EnvironmentObject 传递到视图模型中? [英] SwiftUI - How to pass EnvironmentObject into View Model?

查看:22
本文介绍了SwiftUI - 如何将 EnvironmentObject 传递到视图模型中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望创建一个可以被视图模型(不仅仅是视图)访问的 EnvironmentObject.

I'm looking to create an EnvironmentObject that can be accessed by the View Model (not just the view).

Environment 对象跟踪应用程序会话数据,例如登录、访问令牌等,这些数据将被传递到视图模型(或需要的服务类)中,以允许调用 API 来从这个 EnvironmentObjects 传递数据.

The Environment object tracks the application session data, e.g. loggedIn, access token etc, this data will be passed into the view models (or service classes where needed) to allow calling of an API to pass data from this EnvironmentObjects.

我尝试将会话对象从视图传递给视图模型类的初始化程序,但出现错误.

I have tried to pass in the session object to the initialiser of the view model class from the view but get an error.

如何使用 SwiftUI 访问/传递 EnvironmentObject 到视图模型中?

how can I access/pass the EnvironmentObject into the view model using SwiftUI?

推荐答案

下面提供了适合我的方法.测试了许多从 Xcode 11.1 开始的解决方案.

Below provided approach that works for me. Tested with many solutions started with Xcode 11.1.

问题源于在view中注入EnvironmentObject的方式,一般schema

The problem originated from the way EnvironmentObject is injected in view, general schema

SomeView().environmentObject(SomeEO())

即,首先创建视图,第二个创建环境对象,第三个环境对象注入视图

ie, at first - created view, at second created environment object, at third environment object injected into view

因此,如果我需要在视图构造函数中创建/设置视图模型,则环境对象尚不存在.

Thus if I need to create/setup view model in view constructor the environment object is not present there yet.

解决方案:分解一切,使用显式依赖注入

Solution: break everything apart and use explicit dependency injection

这是它在代码中的样子(通用架构)

Here is how it looks in code (generic schema)

// somewhere, say, in SceneDelegate

let someEO = SomeEO()                            // create environment object
let someVM = SomeVM(eo: someEO)                  // create view model
let someView = SomeView(vm: someVM)              // create view 
                   .environmentObject(someEO)

这里没有任何权衡,因为 ViewModel 和 EnvironmentObject 按照设计是引用类型(实际上,ObservableObject),所以我在这里和那里只传递引用(又名指针).

There is no any trade-off here, because ViewModel and EnvironmentObject are, by design, reference-types (actually, ObservableObject), so I pass here and there only references (aka pointers).

class SomeEO: ObservableObject {
}

class BaseVM: ObservableObject {
    let eo: SomeEO
    init(eo: SomeEO) {
       self.eo = eo
    }
}

class SomeVM: BaseVM {
}

class ChildVM: BaseVM {
}

struct SomeView: View {
    @EnvironmentObject var eo: SomeEO
    @ObservedObject var vm: SomeVM

    init(vm: SomeVM) {
       self.vm = vm
    }

    var body: some View {
        // environment object will be injected automatically if declared inside ChildView
        ChildView(vm: ChildVM(eo: self.eo)) 
    }
}

struct ChildView: View {
    @EnvironmentObject var eo: SomeEO
    @ObservedObject var vm: ChildVM

    init(vm: ChildVM) {
       self.vm = vm
    }

    var body: some View {
        Text("Just demo stub")
    }
}

这篇关于SwiftUI - 如何将 EnvironmentObject 传递到视图模型中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆