es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

SwiftUI + MVVM + DI would be translated as: SwiftUI + MVVM + DI

He pasado algún tiempo investigando esto y he encontrado muchos ejemplos de SwiftUI, MVVM e Inyección de Dependencias por separado, pero ninguno combinado, así que estoy asumiendo que he entendido algo mal.

Tengo una nueva aplicación SwiftUI y estoy planeando usar lo mencionado arriba.

Tengo lo siguiente:

Un DependencyContainer

protocol ViewControllerFactory {
func makeFirstViewController() -> First_ViewModel
func makeSecondViewController() -> Second_ViewModel
}

class DependencyContainer: ObservableObject {
let database = AppDatabase()
}

extension DependencyContainer: ViewControllerFactory {
func makeFirstViewController() -> First_ViewModel {
return First_ViewModel(appDatabase: database)
}

func makeSecondViewController() -> Second_ViewModel {
    return Second_ViewModel()
}

}

En el punto de entrada de mi aplicación tengo:

@main
struct MyApp: App {
var body: some Scene {

    let container = DependencyContainer()

    WindowGroup {
        First_View()
        .environment(\.container, container)
    }
}

}

private struct Container: EnvironmentKey {
static let defaultValue = DependencyContainer()
}

extension EnvironmentValues {
var container: DependencyContainer {
get { self[Container.self] }
set { self[Container.self] = newValue }
}
}

Ahora me encuentro con problemas.
¿Cómo uso el contenedor en las vistas?

struct First_View: View {
@Environment(.container) var container
@ObservedObject private var firstViewModel: First_ViewModel

init() {
    _firstViewModel = container.makeFirstViewController()
}

}

Da error:

“No se puede asignar un valor de tipo ‘First_ViewModel’ al tipo ‘ObservedObject‘”.

Si inyecto el contenedor de la siguiente manera:

struct First_View: View {
@ObservedObject private var firstViewModel: First_ViewModel

init(container: DependencyContainer) {
    _firstViewModel = container.makeFirstViewController()
}

}

Funciona, pero no de la forma en que pensaba que debería funcionar.

Tags:  ,

Answer

  1. Avatar for davy.ai

    Parece que estás intentando inyectar DependencyContainer en tus vistas a través de EnvironmentValues. Sin embargo, el problema que estás enfrentando puede deberse a una concepción errónea sobre cómo funciona ObservedObject.

    ObservedObject es un envoltorio de propiedades que espera recibir una instancia de clase que cumpla con el protocolo ObservableObject. Luego, monitorea los cambios en ese objeto durante el ciclo de vida de la vista y actualiza la vista en consecuencia.

    En tu First_View, estás intentando asignar una instancia de First_ViewModel directamente a un ObservedObject. Esto es incorrecto porque First_ViewModel no cumple con el protocolo ObservableObject.

    Para solucionar este error, debes hacer que First_ViewModel cumpla con el protocolo ObservableObject:

    class First_ViewModel: ObservableObject {
        ...
    }
    

    Luego, puedes usar el contenedor para crear una instancia de First_ViewModel, de esta manera:

    struct First_View: View {
        @Environment(\.container) var container
        @ObservedObject private var firstViewModel: First_ViewModel
    
        init() {
            firstViewModel = container.makeFirstViewController()
        }
    }
    

    Esto debería resolver el error que enfrentabas anteriormente.

    En cuanto a tu confusión sobre cómo usar la Inyección de Dependencias con SwiftUI y MVVM, no hay una solución única para todos. Depende de ti decidir la mejor manera de estructurar tu código para lograr los resultados deseados. En general, usar un DependencyContainer para inyectar dependencias en tus view models es una buena práctica, ya que permite una mayor testabilidad y flexibilidad.

Comments are closed.