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
}
]