SwiftUI 依赖注入
Posted
技术标签:
【中文标题】SwiftUI 依赖注入【英文标题】:SwiftUI Dependency Injection 【发布时间】:2021-09-18 20:42:01 【问题描述】:我有一个 SwiftUI 应用,它是一个基于标签的应用
struct Tab_View: View
var body: some View
TabView
Main1_View().tabItem
Text("Blah 1")
Image("TabBar1")
Main2_View().tabItem
Text("Blah 2")
Image("TabBar2")
每个视图都有自己的视图控制器
struct Main1_View: View
@ObservedObject var viewModel: Main1_ViewModel = Main1_ViewModel()
var body: some View
VStack(spacing:0)
<<< VIEW CODE >>>
ViewModel 示例
class Main1_ViewModel: ObservableObject
@ObservableObject var settings: GameSettings
func Randomise()
dataSource = settings.selectedFramework;
GameSettings 类被多个视图模型使用,是一个 ObservableObject,在任何地方都是该类的相同实例。
我的背景是 C#,使用 CastleWindsor 进行依赖注入。
我的问题:是否有相当于传递 GameSettings 实例的 SwiftUI?
【问题讨论】:
【参考方案1】:由于您要求在另一个 ObservableObject
(视图模型)中使用 ObservableObject
(GameSettings
)并且使用依赖注入,所以事情会有点复杂。
为了将依赖注入的ObservableObject
注入到View
,通常的解决方案是使用@EnvironmentObject
。但是,您必须将对象从视图传递到其视图模型。在我的示例中,我在onAppear
中完成了该操作。副作用是对象是视图模型上的一个可选属性(您可以通过设置一个虚拟初始值来解决这个问题)。
因为嵌套的ObservableObject
s 不适用于@Published
类型(适用于值类型,而不是引用类型),所以您需要确保使用objectWillChange
将 GameSettings
的任何更改传递给父视图模型,我使用 Combine
完成了。
DispatchQueue.main.asyncAfter
部分只是为了表明当GameSettings
中的值更改时,视图确实实际上会更新。
(请注意,我还更改了您的类型名称以使用 Swift 的骆驼大小写约定)
import SwiftUI
import Combine
struct ContentView: View
@StateObject private var settings = GameSettings()
var body: some View
TabView
Main1View().tabItem
Text("Blah 1")
Image("TabBar1")
Main2View().tabItem
Text("Blah 2")
Image("TabBar2")
.environmentObject(settings)
struct Main1View: View
@EnvironmentObject var settings: GameSettings
@StateObject var viewModel: Main1ViewModel = Main1ViewModel()
var body: some View
VStack(spacing:0)
Text("Game settings: \(viewModel.settings?.myValue ?? "no value")")
.onAppear
viewModel.settings = settings
DispatchQueue.main.asyncAfter(deadline: .now() + 2)
settings.myValue = "changed"
class GameSettings : ObservableObject
@Published var myValue : String = "Test"
class Main1ViewModel: ObservableObject
private var cancellable : AnyCancellable?
var settings: GameSettings?
didSet
print("Running init on Main1ViewModel")
self.objectWillChange.send()
cancellable = settings?.objectWillChange.sink(receiveValue: _ in
print("Sending...")
self.objectWillChange.send()
)
struct Main2View : View
var body: some View
Text("Hello, world!")
【讨论】:
这回答了你的问题吗?以上是关于SwiftUI 依赖注入的主要内容,如果未能解决你的问题,请参考以下文章
如何调整我的视图模型以实现依赖注入 swiftui(用于以后的单元测试)
IOC 控制反转Android 视图依赖注入 ( 视图依赖注入步骤 | 视图依赖注入代码示例 )