GO FURTHER, FASTER: Try the Swift Career Accelerator today! >>

SOLVED: SwiftUI Preview Crashes with CoreData

Forums > SwiftUI

Hi guys,

Here is the code:

import SwiftUI

struct ContentView: View {
    @Environment(\.managedObjectContext) var moc

    @FetchRequest(sortDescriptors: [
        SortDescriptor(\.date, order: .reverse),
        SortDescriptor(\.title)
    ]) var notes: FetchedResults<Note>

    let relativeDateTimeFormatter = RelativeDateTimeFormatter()

    @State private var showingAlert = false
    @State private var noteTitle = ""
    @State private var noteDescription = ""
    @State private var navigateToNoteView = false

    var body: some View {
        NavigationStack {
            List {
                ForEach(notes) { note in
                    NavigationLink {
                        NoteView(note: note)
                    } label: {
                        HStack {
                            VStack(alignment: .leading) {

                                Text(note.wrappedTitle)
                                    .font(.title2)

                                Text(note.wrappedDescription)
                                    .font(.caption)
                            }

                            Spacer()
                            Text(relativeDateTimeFormatter.localizedString(for: note.wrappedDate, relativeTo: Date()))
                                .font(.caption)
                                .italic()

                        }
                    }

                }
                .onDelete { offsets in
                    DataController().deleteNote(at: offsets, moc: moc, notes: Array(notes))
                }
            }
            .alert("New note", isPresented: $showingAlert) {
                TextField("Note title", text: $noteTitle)
                TextField("Note description", text: $noteDescription)

                Button("Cancel") { showingAlert = false }
                Button("Ok") {
                    if noteTitle.isEmpty || noteDescription.isEmpty {
                        return
                    } else {
                        DataController().addNote(moc: moc, title: noteTitle, description: noteDescription, text: "")
                        noteTitle = ""
                        noteDescription = ""
                        navigateToNoteView = true
                    }
                }
            }
            .navigationTitle("Notes")
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button {
                        showingAlert = true
                    } label: {
                        Image(systemName: "square.and.pencil")
                    }
                }
                ToolbarItem(placement: .navigationBarLeading) {
                    EditButton()
                }
            }
            .navigationDestination(isPresented: $navigateToNoteView) {
                let note = DataController().getLastNote(moc: moc)
                NoteView(note: note ?? DataController.exampleNote)
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var dataController = DataController()
    static var previews: some View {
        Group {
            ContentView()
            ContentView()
                .preferredColorScheme(.dark)
        }
        .environment(\.managedObjectContext, dataController.container.viewContext)
    }
}

I know that the line that trigger the crash of the preview is this: NoteView(note: note ?? DataController.exampleNote) used in NavigationDestination.

Do you know how to solve?

Thanks

2      

Have you tried setting breakpoints to see where it's crashing?

2      

@deirdresm Yes, it crashes in this line: NoteView(note: note ?? DataController.exampleNote).

I tried to comment it and it works fine without crashing. But I don't know why...

2      

hi,

the thing that sticks out to me is that you are not making calls to a fixed DataController that was passed in, say, through the environment. rather, all your calls have the form

DataController().doSomething( ... )

which means that every such call creates its own instance of a DataController.

for example, the statement

DataController().addNote(moc: moc, title: noteTitle, description: noteDescription, text: "")

creates a new data controller, adds a new note, and then this instance of a data controller goes away.

similarly, i would think that

let note = DataController().getLastNote(moc: moc)

always returns a nil value, since a new data controller instance has (probably) no notes.

(i can't tell exactly what DataController.exampleNote is for the case that note is nil.)

hope that helps,

DMG

2      

Go further, faster with the Swift Career Accelerator.

GO FURTHER, FASTER Unleash your full potential as a Swift developer with the all-new Swift Career Accelerator: the most comprehensive, career-transforming learning resource ever created for iOS development. Whether you’re just starting out, looking to land your first job, or aiming to become a lead developer, this program offers everything you need to level up – from mastering Swift’s latest features to conquering interview questions and building robust portfolios.

Learn more here

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.