list isn't updating when I add a new item

Hi everyone, I following 100 days of SwiftUI course , I used same idea of iExpense project exactly but without .sheet method, The list isn't updating when I add new item from AddView.

struct MainView: View {
    var body: some View {
        TabView {
            ContentView() 
                .tabItem {
                    Image(systemName: "1.lane")
                    Text("One")
                }
            AddView(expenses: Expenses())
                .tabItem {
                    Image(systemName: "2.lane")
                    Text("Two")
                }
        }
    }
}

other codes same as iExpense project...

How to fix that ?

The project in GitHub: https://github.com/mahoozi97/iExpense-project

Thanks in advance

Answered by mahoozi97 in 765759022

I got the solution.

Changes to MainView:

struct MainView: View {
    // Create your expenses object in the main view
    @StateObject var expenses = Expenses()
    // This is necessary for switching between tabs
    @State var selectedTab = 0

    var body: some View {
        // Use selection initializer for TabView
        TabView(selection: $selectedTab) {
            ContentView()
                .tabItem {
                    Image(systemName: "1.lane")
                    Text("One")
                }
                // we assign tag to programmatically switch between tabs
                .tag(1)
            // Also we pass selectedTab to AddView so that we can go back to ContentView programmatically
            AddView(selectedTab: $selectedTab)
                .tabItem {
                    Image(systemName: "2.lane")
                    Text("Two")
                }
                // we assign tag to programmatically switch between tabs
                .tag(2)
        }
        // Inject expenses object into environment so that ContentView and AddView can access it
        .environmentObject(expenses)
    }
}

Changes to ContentView:

struct ContentView: View {
    // This is how we can access expenses object in the environment
    @EnvironmentObject var expenses: Expenses

    var body: some View {
        NavigationView {
            List {
                ForEach(expenses.items, id: \.id) { item in
                    HStack {
                        VStack(alignment: .leading) {

                            {....same......}

// Pay attention that you need to add .environmentObject in previews to make it work
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .environmentObject(Expenses())
    }
}

Changes to AddView:

struct AddView: View {
    // This is how we can access expenses object in the environment
    @EnvironmentObject var expenses: Expenses

    @State private var name = ""
    @State private var type = "personal"
    @State private var amount = 0.0

    // Here we pass selectedTab binding
    @Binding var selectedTab: Int

    let types = ["Business", "Personal"]

    @Environment(\.dismiss) var dismiss

    var body: some View {
        NavigationView {
            Form {
                TextField("name", text: $name)

                Picker("Type", selection: $type) {
                    ForEach(types, id: \.self) {
                        Text($0)
                    }
                }
                TextField("Amount", value: $amount, format: .currency(code: Locale.current.currency?.identifier ?? "BD"))
                    .keyboardType(.decimalPad)
            }
            .navigationTitle("Add new expense")
            .toolbar {
                Button("Save") {

                    let item = ExpenseItem(name: name, type: type, amount: amount)

                    expenses.items.append(item)
                    // This is how we jump back to ContentView upon pressing save
                    selectedTab = 1
                }
            }
        }
    }
}

// Pay attention that you need to add .environmentObject in previews to make it work
struct AddView_Previews: PreviewProvider {
    static var previews: some View {
        AddView(selectedTab: .constant(2))
            .environmentObject(Expenses())
    }
}

I got it from : https://www.hackingwithswift.com/forums/swiftui/list-isn-t-updating-when-i-add-a-new-item/23977/23981

What List, there is none in the code you posted. So please post the relevant code parts, not just a link to Github.

Hi @Claude31

struct ContentView: View {
    @StateObject var expenses = Expenses()
    
    var body: some View {
        NavigationView {
            List {
                ForEach(expenses.items, id: \.id) { item in
                    HStack {
                        VStack(alignment: .leading) {
                            
                            Text(item.name)
                                .font(.headline)
                            Text(item.type)
                        }
                        
                        Spacer()
                        
                        Text(item.amount, format: .currency(code: Locale.current.currency?.identifier ?? "BD"))
                            .foregroundColor(item.amount <= 10 ? .green : item.amount <= 100 ? .orange : .red)
                            
                    }
                }
                .onDelete(perform: removeItem)

Add item code in AddView:

Button("Save") {
                    
                    let item = ExpenseItem(name: name, type: type, amount: amount)
                   
                    expenses.items.append(item)
                }
Accepted Answer

I got the solution.

Changes to MainView:

struct MainView: View {
    // Create your expenses object in the main view
    @StateObject var expenses = Expenses()
    // This is necessary for switching between tabs
    @State var selectedTab = 0

    var body: some View {
        // Use selection initializer for TabView
        TabView(selection: $selectedTab) {
            ContentView()
                .tabItem {
                    Image(systemName: "1.lane")
                    Text("One")
                }
                // we assign tag to programmatically switch between tabs
                .tag(1)
            // Also we pass selectedTab to AddView so that we can go back to ContentView programmatically
            AddView(selectedTab: $selectedTab)
                .tabItem {
                    Image(systemName: "2.lane")
                    Text("Two")
                }
                // we assign tag to programmatically switch between tabs
                .tag(2)
        }
        // Inject expenses object into environment so that ContentView and AddView can access it
        .environmentObject(expenses)
    }
}

Changes to ContentView:

struct ContentView: View {
    // This is how we can access expenses object in the environment
    @EnvironmentObject var expenses: Expenses

    var body: some View {
        NavigationView {
            List {
                ForEach(expenses.items, id: \.id) { item in
                    HStack {
                        VStack(alignment: .leading) {

                            {....same......}

// Pay attention that you need to add .environmentObject in previews to make it work
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .environmentObject(Expenses())
    }
}

Changes to AddView:

struct AddView: View {
    // This is how we can access expenses object in the environment
    @EnvironmentObject var expenses: Expenses

    @State private var name = ""
    @State private var type = "personal"
    @State private var amount = 0.0

    // Here we pass selectedTab binding
    @Binding var selectedTab: Int

    let types = ["Business", "Personal"]

    @Environment(\.dismiss) var dismiss

    var body: some View {
        NavigationView {
            Form {
                TextField("name", text: $name)

                Picker("Type", selection: $type) {
                    ForEach(types, id: \.self) {
                        Text($0)
                    }
                }
                TextField("Amount", value: $amount, format: .currency(code: Locale.current.currency?.identifier ?? "BD"))
                    .keyboardType(.decimalPad)
            }
            .navigationTitle("Add new expense")
            .toolbar {
                Button("Save") {

                    let item = ExpenseItem(name: name, type: type, amount: amount)

                    expenses.items.append(item)
                    // This is how we jump back to ContentView upon pressing save
                    selectedTab = 1
                }
            }
        }
    }
}

// Pay attention that you need to add .environmentObject in previews to make it work
struct AddView_Previews: PreviewProvider {
    static var previews: some View {
        AddView(selectedTab: .constant(2))
            .environmentObject(Expenses())
    }
}

I got it from : https://www.hackingwithswift.com/forums/swiftui/list-isn-t-updating-when-i-add-a-new-item/23977/23981

list isn't updating when I add a new item
 
 
Q