Контекст
У меня есть довольно простой Form, использующий MVVM архитектуру. Однако я столкнулся с проблемой этой реализации. У моего DetailView есть DummyState, который изменяет соответствующий атрибут EntityonChange.
Проблема: как только появляется
DetailView, обаTogglesвключены, как и ожидалось. Однако при отключении местногоToggleостается включенным другойToggle, что неожиданно. Однако, как только я взаимодействую с другим элементом (не вMRE), кажется, что второйToggleобновляется и отключается.
Код
@objc(Entity) public class Entity: NSManagedObject {
@NSManaged public var enabled: Bool
}
class FormViewModel: ObservableObject, CustomFormObservable {
@Published var entity = Entity(context: ...)
init() { self.entity.enabled = true }
var isValid: Bool { self.entity.enabled }
}
struct FormView: View {
@StateObject private var formVM = FormViewModel()
var body: some View {
CustomForm(formVM: formVM) {
DetailView(entity: $formVM.entity)
}
}
}
struct DetailView: View {
@Binding var entity: Entity
@State private var localEnabled: Bool = true
var body: some View {
Toggle("Local Toggle", isOn: $localEnabled)
.onChange(of: localEnabled) { entity.enabled = $0 }
Toggle("Toggle", isOn: $entity.enabled)
}
}
Вопрос
Все объекты CoreData должны быть обернуты в ObservedObject, их переменные типа значения могут использовать Binding
@loremipsum большое спасибо за ваш ответ и ресурс. Для меня это имеет смысл, однако я обновил свой код, а также MRE и столкнулся с другой проблемой. Смотрите текущий ответ и его комментарии. У вас есть какие-либо идеи, что вызывает это?
Entity имеет неправильную оболочку, и ваша виртуальная машина не может наблюдать за наблюдаемым объектом. Это лишний ненужный слой.
@loremipsum Спасибо за ваш ответ. Какую оболочку сущности вы имеете в виду? И как упростить код, убрав слой? Небольшой пример кода был бы очень признателен.
Вадиан уже дал тебе код





Потому что NSManagedObject — это ссылочный тип.
Есть простое правило:
@State и @Binding предназначены для типов значений, таких как структуры.@StateObject и @ObservedObject предназначены для ссылочных типов, таких как классы.И ссылка на знак доллара также только для типов значений.
К счастью, NSManagedObject по умолчанию соответствует ObservableObject.
struct MainView: View {
@StateObject private var formVM = FormViewModel()
var body: some View {
DetailView(entity: formVM.entity)
}
}
struct DetailView: View {
@ObservedObject var entity: Entity
@State private var localEnabled: Bool = true
var body: some View {
Toggle("Local Toggle", isOn: $localEnabled)
.onChange(of: localEnabled) { entity.enabled = $0 }
Toggle("Toggle", isOn: $entity.enabled)
}
}
Большое спасибо за вашу поддержку! Это реализация, которая у меня была раньше. Однако при изменении ObservedObject в DetailView@Published var entity в FormViewModel не обновляется. Именно по этой причине я перешел на Binding. Любая идея о том, как решить эту проблему?
Я добавил дополнительный код в файл MRE. У меня также есть вычисляемое свойство isValid, которое используется для проверки того, должна ли кнопка «Сохранить» быть неразрешимой. Когда я сказал в своем предыдущем комментарии, что представление не обновляется, я имел в виду, что кнопка Save не становится интерактивной, даже если условие выполнено.
Вместо вычисляемого свойства, которое на самом деле тоже должно быть @Published, используйте formVM.entity.enabled в представлении. Все свойства NSManaged публикуются.
Большое спасибо за ваш ответ, но я не совсем понимаю ваше предложение. CustomForm является общим и принимает ViewModel, соответствующий CustomFormObservable, для которого требуется свойство isValid. У меня нет доступа к конкретному свойству entity изнутри CustomForm, чтобы проверить, должна ли кнопка «Сохранить» быть неразрешимой, эта логика должна быть передана на аутсорсинг.
На самом деле это новый вопрос. Мой ответ решает проблему @Binding. Поскольку NSManagedObject соответствует ObservableObject, вы можете реализовать Combine Publisher, который управляет свойством isValid.
Ты прав. Я принял ваш ответ и задал новый вопрос по этой теме: stackoverflow.com/questions/76296952/…