I would like to add a Product
to a Shop
's container but i can't and i don't understand why because my Shop
is var and not let.
My goal is to put a Product
into a Shop
like this:
input Shop(name: "Apple Store", container: [])
output: Shop(name: "Apple Store", container: [Product(name: "Cheese")])
Here is My code:
import SwiftUI
struct Shop: Identifiable {
let name: String
var container: [Product]
var id = UUID()
}
struct Product: Identifiable {
let name: String
var id = UUID()
}
struct ContentView: View {
@State var shops: [Shop] = [
Shop(name: "Apple Store", container: []),
Shop(name: "StopShop", container: [Product(name: "milk")])
]
var body: some View {
NavigationView {
List {
ForEach(shops) { shop in
NavigationLink(shop.name, destination: {
List {
ForEach(shop.container) { product in
Text(product.name)
}
}
.navigationBarTitle(shop.name)
.navigationBarItems(trailing: Button {
shop.container.append(Product(name: "Cheese"))
} label: {
Text("add").bold()
})
})
}
}
.navigationBarTitle("Shops")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
I have tried by append or insert it and i expected it to work but it didn't. :(
CodePudding user response:
The error tells the truth: Index variables in a loop are constants in Swift (since the initial release).
Due to value semantics you have to modify the Shop
element in the shops
array directly.
Add a function inside the view
func appendProduct(_ product: Product, to shop: Shop) {
guard let index = shops.firstIndex(where: {$0.id = shop.id}) else { return }
shops[index].container.append(product)
}
and call it
.navigationBarItems(trailing: Button {
appendProduct(Product(name: "Cheese"), to: shop)
} label: {
Text("add").bold()
})
CodePudding user response:
Your problem here is that you are not modifying the struct's
@State var shops: [Shop]
You are trying to change the element iterated on the foreach, which is, in fact, a let.
ForEach(shops) { shop in // shop here is a let
Knowing that, you should be able to modify your code to make the proper implementation.
So for example, if you want to modify the struct's param, you can:
ForEach(Array(shops.enumerated()), id: \.offset) { index, element in
// ...
shops[index].container.append(Product(name: "Cheese"))
}
(This is a draft example, you can do it however you think its best)