0

I am writing a swiftui-app for iPhone. The products are downloaded from an URL via await loadData() and pushed to the State-variable products. I initially incremented/decremented the class-variable product.count. Printing the variable to the console confirmed counter was updated, but remained unchanged at 0 in the list. I ended up declaring another State-variable pCount that does show the correct count. But shadowing the counter to a secondary variable does not seem like a good way to solve this.

I attempted to declare the class as ObservableObject and the variable as StateObject but then had to change func loadData() async {} as mutable and that would not compile.

Is it because I'm using a class-variable counter is not updated in the list?

struct PurchaseView: View {
    @State private var products: [Product] = []
    @State private var pCount: [String: Int] = [:]
    
    var body: some View {
        NavigationStack {
            List {
                ForEach(products) { product in
                    VStack(alignment: .leading) {
                        let p = Double(product.price)!

                        let plusButton = Button() {} label: {
                            Image(systemName: "plus.circle.fill").symbolRenderingMode(.multicolor)
                        }
                        .onTapGesture {
                            //product.count += 1 <-- First attempt, not updating counter
                            pCount[product.id]! += 1
                            product.count = pCount[product.id]!
                            purchaseButtonText = formatPurchaseButtonText(sum: pSum)
                        }

                        let minusButton = Button() {} label: {
                            Image(systemName: "minus.circle.fill").symbolRenderingMode(.multicolor)
                        }
                        .onTapGesture {
                            //product.count -= 1 <-- First attempt, not updating counter
                            pCount[product.id]! -= 1
                            product.count = pCount[product.id]!
                            purchaseButtonText = formatPurchaseButtonText(sum: pSum)
                        }

                        HStack {
                            Text("\(product.name), \(p, specifier: "%.0f")").font(.headline)
                            minusButton.frame(maxWidth: .infinity, alignment: .trailing)
                            //Text("\(product.count)") <-- First attempt, not updating counter
                            Text("\(pCount[product.id] ?? 0)")
                            plusButton
                        }
                    }
                }
            }
            .navigationTitle("Purchase")
        }
        .task {
            await loadData()
        }
    }
}
func loadData() async {
    // GET json from URL
    for result in products {
        if pCount[result.id] == nil {
            pCount[result.id] = result.count
        }
    }
}

class Product: Identifiable, Codable {
    var id: String = ""
    var name: String = ""
    var price: String = ""
    var count: Int = 0
}

[
  {
    "id": "6626e52f-34cc-4e3a-a244-60598a754ba4",
    "name": "soda",
    "price": "2.000",
    "count": 0
  }
]

products

kometen
  • 6,536
  • 6
  • 41
  • 51
  • 1
    As the linked duplicate explains, you should only use `@State` with value types. `@State` doesn't update the view when a property of a reference type changes, since it only updates the view when the `@State` variable itself changes and for reference types, that only happens when you replace the reference itself. – Dávid Pásztor Apr 18 '23 at 10:00
  • 1
    You shouldn't be calling `loadData` on the view directly, move it to your `ObservableObject` conformant model object instead and then you don't have to make it `mutable`. – Dávid Pásztor Apr 18 '23 at 10:00
  • Thank you. I used an example loading data from Paul Hudson. This covers the basic and may not be suitable for all scenarios. https://www.hackingwithswift.com/books/ios-swiftui/sending-and-receiving-codable-data-with-urlsession-and-swiftui – kometen Apr 18 '23 at 10:10

0 Answers0