Learn Courses My Dashboard

App is crashing

I was building a small todo app and as soon as I want to add the data to it, the app gets crashed. Please help
here is the link the app is very small so it won’t take long time to examine

@riskjockeyy

I think I have fixed it but I have Xcode 13.4 rather than what would appear to be Xcode 14 that you are possibly using???. (I personally steer clear of Beta software since I don’t want the aggravation of dealing with potential bugs that exist in Beta software. Each to his own I say).

The issue causing the crash is that you had the .environmentObject() injected in the Parent View but inside the NavigationStack attached to ListView rather than to the closing brace of the NavigationStack.

Now since I have Xcode 13.4 I changed NavigationStack to NavigationView so that the App would at last work for me.

Having solved the crash issue I then added an item but it didn’t appear in the ListView. I thought this was a bit weird so did some debugging and it looked like it should be working properly since addItem was being called in the View Model and each line of code in that function was being executed.

Hunted around for some other possible culprits. I saw that you has injected .environmentObject to both the AddView and to the ListView. Removed both of those and the App works a treat.

Here are each of the Views that I made alterations to.

ToDoApp.swift

@main
struct ToDoApp: App {
    var body: some Scene {
        WindowGroup {
            NavigationView {  // Change this back to NavigationStack if you want to.
                ListView()
            }
            .environmentObject(TodoDataModel())
        }
    }
}

ListView:

struct ListView: View {
    @EnvironmentObject var model: TodoDataModel
    
    var body: some View {
        List {
            ForEach(model.dataToAdd) { item in
                VStack {
                    HStack {
                        Image(systemName: item.isCompleted ?  "checkmark.circle" : "circle")
                            .foregroundColor(item.isCompleted ? .green : .red)
                        Text(item.item)
                    }
                    .foregroundColor(.primary)
                }
            }.onDelete { indexSet in
                model.delete(indexSet: indexSet)
            }
            .onMove { IndexSet, to in
                model.move(indexSet: IndexSet, to: to)
            }
        }
        .navigationTitle("Todo List")
        .navigationBarItems(leading: EditButton(), trailing: NavigationLink(destination: {
            AddView()
        }, label: {
            Image(systemName: "plus")
        }))
    }
}

struct ListView_Previews: PreviewProvider {
    static var previews: some View {
        ListView()
            .environmentObject(TodoDataModel())
    }
}

AddView:

struct AddView: View {
    @Environment(\.presentationMode) var presentationMode
    @EnvironmentObject var model: TodoDataModel
    @State var name = ""
    
    var body: some View {
        VStack {
            TextField("What do you want to add", text: $name)
                .padding(.horizontal)
                .frame(height: 55)
                .background(Color.teal)
                .cornerRadius(10)

            Button {
                // save item
                model.addItem(title: name)
                presentationMode.wrappedValue.dismiss()

            } label: {
                Text("Save")
                    .foregroundColor(.white)
                    .frame(height: 55)
                    .frame(maxWidth: .infinity)
                    .background(Color.blue)
                    .cornerRadius(10)
            }
            Text("\(name)")
        }
        .navigationTitle("Add an item")
    }
}

struct AddView_Previews: PreviewProvider {
    static var previews: some View {
        AddView()
    }
}

Let me know how that goes with those changes.

Thank you so much Chris . you are a life saver. putting the .environmentObject property wrapper to NavigationStack instead of ListView() worked. I did not had to change anything else. I am really happy now and glad to go with CWC + . I know you guys will always save me from such stupid mistake.

import SwiftUI

@main
struct ToDoApp: App {
    var body: some Scene {
        WindowGroup {
            NavigationStack {
                ListView()
                    
            }
            .environmentObject(TodoDataModel())
        }
    }
}

Also, I am really sorry for installing the beta version. I actually install the macOS ventura and then I did not have any other option than using Xcode 14. because my older Xcode stopped working. From now I will take care of it.

@riskjockeyy

Does that mean that you left the .enviromentObject() injections in the ListView and AddView files? If you have, can you successfully add new items to the array dataToAdd?

yes the app works even if I remove them from ListView and AddView. I added them so that I could solve the crashing problem .

If you require the Observable Object in a number of Views that are child Views of the parent then you should inject the .environmentObject() into the parent.