#swiftui #nsmanagedobjectcontext
#swiftui #nsmanagedobjectcontext
Вопрос:
Передать контекст управляемого объекта в представление в SwiftUI достаточно просто, используя переменную @Environment. Но получение того же контекста для модели и модели представления, не так много. Вот что я пробовал:
Я создал свойство с именем context в модели представления. В представлении я передаю контекст управляемого объекта лениво. Проблема в том, что теперь я получаю сообщение об ошибке при вызове метода модели представления из представления — «Невозможно использовать изменяющийся геттер для неизменяемого значения: ‘self’ неизменяем». Метод работал до того, как я добавил контекст, так почему же он перестал работать? И, что более важно, как мне заставить это работать?!
Модель:
struct Model {
//use fetch request to get users
func checkLogin(username: String, password: String) {
for user in users {
if username == user.userEmail amp;amp; password == user.password {
return true
}
}
return false
}
}
Просмотр модели:
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)
}
}
И, наконец, представление:
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")
}
}
Ответ №1:
Вы не можете использовать lazy var
в представлении, потому что оно неизменяемо. Вот возможный подход к решению вашего случая
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
}
}
}
Комментарии:
1. Это работает, но поскольку модель представления не работает без контекста, у нас не должно быть пустого инициализатора, который позволяет это. Я думаю, что Apple скоро представит механизм для передачи переменных среды из представлений SwiftUI в пользовательские типы (например, модели представлений).