BLACK FRIDAY SALE: Save big on all my Swift books and bundles! >>

Save the list after updating

Forums > SwiftUI

Im trying to add more functionalities to the iExpense App from the 100 days of SwiftUI. I was able to open a new page upon clicking the row of list and is able to update the information but is unable to save it. I need a code to save the details in the UpdateDetails View. I have marked the section I need help with.

ContentView

struct ContentView: View {

    @ObservedObject var expenses = Expenses()
    @State private var showingAddExpense = false

    var body: some View {

        NavigationView {

                List {
                    ForEach(expenses.items) { item in

                        NavigationLink(destination: UpdateDetails(expenses: expenses, name: item.name, amount: item.amount)) {

                            VStack(alignment: .leading, spacing : 10) {
                                Text(item.name)
                                    .font(.headline)
                                HStack {
                                    Text("Count:")
                                    Text(item.amount, format: .currency(code: ""))

                                }

                            }
                        }

                    }
                    .onDelete(perform: removeItems)
                    .onMove(perform: move)

                }

                .toolbar {

                    EditButton()

                    Button {
                        showingAddExpense = true
                    } label: {

                        NavigationLink(destination: AddView(expenses: expenses)) {
                            Image(systemName: "plus")
                        }

                    }

                }

            .navigationTitle("Counter")

        }

    }

    func move(indices: IndexSet, newOffset: Int){
        expenses.items.move(fromOffsets: indices, toOffset: newOffset)
    }

    func removeItems(at offsets: IndexSet) {
        expenses.items.remove(atOffsets: offsets)
    }

}

AddView:

struct AddView: View {

    @State private var name = ""
    @State private var amount = 0

    @ObservedObject var expenses: Expenses
    @Environment(\.dismiss) var dismiss

    var body: some View {

                    Form {

                        TextField("Name", text: $name)
                        Text("\(amount)")
                        Button("Tap Me") {
                            amount += 1
                        }

                    }
                    .navigationTitle("Add New Count")
                    .toolbar {

                        if name != "" {

                            Button("Save") {
                                let item = ExpenseItem(name: name, amount: amount)
                                expenses.items.append(item)
                                dismiss()

                            }
                        }
                    }
    }
}

Expense Item:

struct ExpenseItem : Identifiable, Codable {
    var id = UUID()
    let name: String
    let amount: Int
}

Expense Model :

class Expenses: ObservableObject {

    @Published var items = [ExpenseItem]() {
        didSet {
            if let encoded = try? JSONEncoder().encode(items) {
                UserDefaults.standard.set(encoded, forKey: "Items")
            }
        }
    }

    init() {
        if let savedItems = UserDefaults.standard.data(forKey: "Items") {
            if let decodedItems = try? JSONDecoder().decode([ExpenseItem].self, from: savedItems) {
                items = decodedItems
                return
            }
        }

        items = []
    }
}

UpdateDetails :

struct UpdateDetails: View {

    @StateObject var expenses : Expenses
    @Environment(\.dismiss) var dismiss

    @State var name : String
    @State var amount : Int

    var body: some View {

        Form {

            TextField("Name", text: $name)
            Text("\(amount)")
            Button("Tap Me") {
                amount += 1
            }

        }
        .navigationTitle("Update Count")
        .toolbar {

            if name != "" {

                    Button("Update") {
                        let item = ExpenseItem(name: name, amount: amount)

                        // Save the updated details......

                        dismiss()
                    }

            }
        }
    }
}

   

Hello. I'm trying to save the updated data. If I use append, it will goto the end of the list and I will end up having two of the same items in the list. One with the original data and one with updated data. What I'm trying to do is when I press update I want the original data in the list to be replaced by the updated data.

   

In your ExpenseItem struct both name and amount are defined with let and aren't editable. So, you can't edit them. You would have to change them to var.

The reason why everytime a new item is created is: in your UpdateDetails View you create a new ExpenseItem and you don't edit the old one. As mentioned above, you wouldn't be able to change name and amount of an existing ExpenseItem anyway.

It's not useful to just copy the AddView, rename it and expect that it would have a different behaviour in a different scenario. Your underlying data model doesn't even allow editing of an ExpenseItem.

I would suggest:

  • Follow this tutorial on how to create a Detail View
  • Then adapt the data model that it allows editing of an item
  • Then adapt your wanted changes to your version of iExpense

Then try again and show us your progress.

   

Hacking with Swift is sponsored by RevenueCat

SPONSORED In-app subscriptions are a pain to implement, hard to test, and full of edge cases. RevenueCat makes it straightforward and reliable so you can get back to building your app. Oh, and it's free if your app makes less than $10k/mo.

Learn more

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

Reply to this topic…

You need to create an account or log in to reply.

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.