Problem
XCode 15 Beta
I'm testing the new Beta version of Xcode and had some problems with the @Binding behavior.
I recreated the approximate view structure. I tried accessing the models array of the Model1 in the second view. Im using the textfield onEditingChanged to display a new view below when something is searched. But when I first tap on the textfield the vm.model1Selection gets set to nil and the vm.selectedModel1 needs to be reselected through a menu. Then on the second try everything works. I tried a lot restructuring the code but the problem stays the same.
During my attempts to fix the problem, I think the problem lies in the following snippet:
if !selectedDepot.securities.isEmpty {
Edit:
I think the main problem is that the values of the variables inside the viewModel get restetted
Code:
Models
@Model
final class Model1 {
@Attribute(.unique) var id: UUID
var name: String
@Relationship(.cascade, inverse: \Model2.model1)
var models: [Model2] = []
init(name: String) {
self.id = UUID()
self.name = name
}
}
@Model
final class Model2 {
@Attribute(.unique) var id: UUID
var name: String
var model1: Model1?
init(name: String) {
self.id = UUID()
self.name = name
}
}
View Model
I've created this ViewModel with the new @Observable feature.
@Observable
class ViewModel {
var model1Selection: Model1? = nil
var model2Selection: Model2? = nil
}
Views
struct ParentView: View {
@Bindable var vm = ViewModel()
@Query(sort: [
SortDescriptor(\.name)
]) var model1Models: [Model1]
var body: some View {
VStack {
Menu {
ForEach(model1Models) { model in
Button(model.name) {
vm.model1Selection = model
}
}
} label: {
HStack {
Text("\(vm.model1Selection?.name ?? "Select a Model")")
}
if let model1 = vm.model1Selection {
ChildView1(selectedModel1: model1, selectedModel2:
$vm.model2Selection)
}
}
.onAppear {
vm.model1Selection = model1Models.first
}
}
}
struct ChildView1: View {
let selectedModel1: Model1
@Binding var selectedModel2: Model2?
@State private var name: String = ""
@State private var searchActive: Bool = false
var body: some View {
VStack {
if selectedModel2 == nil {
TextField("...", text: $name, onEditingChanged: {
self.searchActive = $0
withAnimation {
proxy.scrollTo(anchor, anchor: .top)
}
})
} else {
Text("empty")
}
if searchActive {
if !selectedModel1.models.isEmpty { // <-- accessing models seems to be a problem
ChildView2(selectedModel1: selectedModel1,
selectedModel2: $selectedModel2)
}
}
}
}
}
struct ChildView2: View {
let selectedModel1: Model1
@Binding var selectedModel2: Model2?
var body: some View {
VStack {
ForEach(model1.models) { x in
Text(x.name)
}
}
}
}