I am trying to learn SwiftData, so I created a very simple app (macOS) to learn the basics. I ran into what turns out to be very odd behavior (at least I am not understanding).
In my code below, everything works as expected – Until I comment out the “if” around my Button in ContentView (Look for my <—– in the code) I get the following problem – I run the app and add 1 ‘Note’ to it. Quit the app, and then go back into it and click on the Note I added before – it comes up as Nil, even though I know it is not (the print stmt prints out the UUID).
Put the “if” stmt back in and rerun – it works as expected.
What is happening when the Button view is always there (no if stmt) ?
import SwiftUI
import SwiftData
@main
struct SwiftDataTryApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(for: Note.self)
}
}
@Model
class Note: Identifiable {
var id: String = UUID().uuidString
var titleText: String = ""
var bodyText: String = ""
init() {}
}
struct ContentView: View {
@Environment(.modelContext) var modelContext
@Query var notes: [Note]
@State var showEditNoteView: Bool = false
@State var selectedNote: Note?
var body: some View {
VStack() {
List {
ForEach(notes) { note in
Text(note.titleText)
.onTapGesture {
if !showEditNoteView {
print(note.id)
selectedNote = note
showEditNoteView = true
}
}
}
}
.padding()
if !showEditNoteView { // <------- Without this, I see the problem
Button("+") {
selectedNote = Note()
modelContext.insert(selectedNote!)
showEditNoteView = true
}
}
}
.padding()
.popover(isPresented: $showEditNoteView) {
if selectedNote != nil { EditNoteView(isPresented: $showEditNoteView, note: selectedNote!) }
else { Text("selectedNote is nil") .padding() }
}
}
}
struct EditNoteView: View {
@Environment(.modelContext) var modelContext
@Binding var isPresented: Bool
@Bindable var note: Note
@State var titleText: String = ""
@State var bodyText: String = ""
var body: some View {
VStack() {
TextField("Title", text: $titleText)
TextEditor(text: $bodyText)
Button("Save") { isPresented = false }
}
.padding()
.frame(width: 728, height: 512)
.onAppear {
titleText = note.titleText
bodyText = note.bodyText
}
.onDisappear {
note.titleText = titleText
note.bodyText = bodyText
do {
try modelContext.save()
} catch {
print(error.localizedDescription)
}
}
}
}