Home > OS >  Inject a StateObject into SwiftUI View
Inject a StateObject into SwiftUI View

Time:03-15

Can @StateObject be injected using Resolver?

I have the following:

struct FooView: View {
    @StateObject private var viewModel: FooViewModel

    some code
}
protocol FooViewModel: ObservableObject {
    var someValue: String { get }
    func someRequest()
}

class FooViewModelImpl {
   some code
}

I would like to inject FooViewModel into FooView using Resolver but have been struggling as Resolver wants to use the @Inject annotation and of course, I need the @StateObject annotation but I cannot seem to use both. Are @StateObject not able to be injected using some Dependency Injection framework like Resolver? I have not found any examples where developers have used DI in this approach.

CodePudding user response:

No, @StateObject is for a separate source of truth it shouldn't have any other dependency. To pass in an object, e.g. the object that manages the lifetime of the model structs, you can use @ObservedObject or @EnvironmentObject.

FYI we don't use view models objects in SwiftUI. See this answer "MVVM has no place in SwiftUI."

ObservableObject is part of the Combine framework so you usually only use it when you want to assign the output of a Combine pipeline to an @Published property. Most of the time in SwiftUI and Swift you should be using value types like structs. See Choosing Between Structures and Classes. We use DynamicProperty and property wrappers like @State and @Binding to make our structs behave like objects.

CodePudding user response:

Not sure about resolver but you can pass VM to a V using the following approach.

import SwiftUI

class FooViewModel: ObservableObject {
    @Published var counter: Int = 0
}

struct FooView: View {
    
    @StateObject var vm: FooViewModel
    
    var body: some View {
        VStack {
            Button {
                vm.counter  = 1
            } label: {
                Text("Increment")
            }
        }
    }
}

struct ContentView: View {
    var body: some View {
        FooView(vm: FooViewModel())
    }
}
  • Related