SwiftUI: passaggio del contesto dell'oggetto gestito al modello
Il passaggio di un contesto oggetto gestito a una vista in SwiftUI è abbastanza semplice utilizzando una variabile @Environment. Ma ottenere lo stesso contesto per il modello e il modello di visualizzazione, non così tanto. Ecco cosa ho provato:
Ho creato una proprietà chiamata contesto nel modello di visualizzazione. Nella visualizzazione, passo pigramente il contesto dell'oggetto gestito. Il problema è che ora ricevo un errore quando chiamo il metodo di un modello di visualizzazione dalla vista: "Non è possibile utilizzare getter mutante su un valore immutabile: 'self' è immutabile". Il metodo ha funzionato prima di aggiungere il contesto, quindi perché ha smesso di funzionare? E, cosa più importante, come faccio a farlo funzionare ?!
Modello:
struct Model {
//use fetch request to get users
func checkLogin(username: String, password: String) {
for user in users {
if username == user.userEmail && password == user.password {
return true
}
}
return false
}
}
Visualizza modello:
class ViewModel {
var context: NSManagedObjectContext
private var model = Model()
init(context: NSManagedObjectContext) {
self.context = context
}
func checkLogin(username: String, password: String) -> Bool {
model.checklogin(username: username, password: password)
}
}
E infine, la vista:
struct LoginView: View {
@Environment(\.managedObjectContext) var moc
lazy var viewModel = ViewModel(context: moc)
//Login form
Button(action: {
if self.viewModel.checkLogin(username: self.email, password: self.password) {
//ERROR: Cannot use mutating getter on immutable value: 'self' is immutable
//allow login
}
}) {
Text("login")
}
}
Risposte
Non è possibile utilizzarlo lazy var
in View, perché è immutabile. Ecco un possibile approccio per risolvere il tuo caso
class ViewModel {
var context: NSManagedObjectContext?
private var model = Model()
init(context: NSManagedObjectContext? = nil) {
self.context = context
}
func checkLogin(username: String, password: String) -> Bool {
return model.checkLogin(username: username, password: password)
}
}
struct LoginView: View {
@Environment(\.managedObjectContext) var moc
private let viewModel = ViewModel() // no context yet here, so just default
//Login form
var body: some View {
Button(action: {
if self.viewModel.checkLogin(username: self.email, password: self.password) {
//allow login
}
}) {
Text("login")
}
.onAppear {
self.viewModel.context = moc // << set up context here
}
}
}