I'm curious, has anyone run into Xcode preview bugs involving bindings in if-blocks not propagating changes up the hierarchy? More importantly, how do we work around it? These bugs are adding hassle to development. I'd gladly restructure my code (within reason) to avoid preview bugs.
Here's some code that exhibits the bug -- in Xcode Version 14.3.1 (14E300c):
import SwiftUI
struct Record: Identifiable {
var id: UUID
var name: String
}
var records: [Record] = [
Record(id: .init(), name: "Record 1"),
Record(id: .init(), name: "Record 2"),
Record(id: .init(), name: "Record 3")
]
struct RecordList: View {
@Binding var currentRecord: Record?
var body: some View {
VStack {
Text("Selection (Inner): \(currentRecord?.name ?? "Not Selected")")
ForEach(records) { record in
Button {
currentRecord = record
} label: {
Text(record.name)
}
}
}
}
}
struct BrokenPreview: View {
@State private var currentRecord: Record?
var body: some View {
if currentRecord != nil {
VStack {
Text(currentRecord!.name)
Button("Return") { self.currentRecord = nil }
}
} else {
VStack {
Text("Selection (Outer): \(currentRecord?.name ?? "Not Selected")")
RecordList(currentRecord: $currentRecord)
}
}
}
}
When I preview this in Xcode live preview, I start with a list of three buttons. If I tap on one of the buttons, the "Selection (Inner):" updates correctly, but "Selection (Outer):" continues to show "Not Selected". This is nonsense, of course.
Using the simulator gives the behaviour I expect.
I haven't fully narrowed down the conditions for this problem, but it seems to involve bindings being used within a conditional. I haven't installed Xcode 15 betas, so I don't know if they still have this issue. But I'd love a workaround if anyone can help.