英文:
Why does Binding of CoreData NSManagedObject not update onChange in Swift?
问题
问题的原因是在DetailView
中,本地的Toggle
状态改变时,未能正确地触发entity.enabled
的绑定。解决方法是确保在localEnabled
改变时,手动更新绑定的entity.enabled
。可以尝试在DetailView
的onChange
闭包中,显式地将entity.enabled
的值设置为localEnabled
:
.onChange(of: localEnabled) { newValue in
entity.enabled = newValue
}
英文:
Context
I have a pretty simple Form
using the MVVM
architecture. However, I encountered a problem with this implementation. My DetailView
has a DummyState
that changes the corresponding attribute of Entity
onChange
.
> Problem: Once the DetailView
appears, both Toggles
are on which is as expected. However, when turning the local Toggle
off, the other Toggle
remains on, which is unexpected. However, as soon as I interact with another element (not in MRE
), the second Toggle
seems to refresh and turns off.
Code
@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)
}
}
Question
- What causes this behaviour and how can I solve it?
答案1
得分: 1
因为 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("本地切换", isOn: $localEnabled)
.onChange(of: localEnabled) { entity.enabled = $0 }
Toggle("切换", isOn: $entity.enabled)
}
}
英文:
Because NSManagedObject
is reference type.
There is a simple rule:
@State
and@Binding
is for value types like structs.@StateObject
and@ObservedObject
is for reference types like classes.
And the dollar-sign reference is also only for value types.
Fortunately NSManagedObject
conforms to ObservableObject
by default.
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)
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论