UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

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()
                    }

            }
        }
    }
}

1      

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.

1      

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.

1      

BUILD THE ULTIMATE PORTFOLIO APP Most Swift tutorials help you solve one specific problem, but in my Ultimate Portfolio App series I show you how to get all the best practices into a single app: architecture, testing, performance, accessibility, localization, project organization, and so much more, all while building a SwiftUI app that works on iOS, macOS and watchOS.

Get it on Hacking with Swift+

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.