Binding a var from struct array under an ObservableObject

I have an environment object Order, containing a list of OrderItem (aka an item + a quantity) I'm presenting a list with steppers so quantity can be modified for each item.
struct MenuItem: Codable, Hashable, Identifiable {
var id: UUID
var name: String
var price: Int
}
struct OrderItem: Hashable, Identifiable {
var item: MenuItem
var quantity: Int
var id: UUID
}
class Order: ObservableObject {
@Published var items = [OrderItem]()
}
struct OrderView: View {
@EnvironmentObject var order: Order
var body: some View {
List {
Section("My Order") {
ForEach($order.items) { $orderItem in
VStack {
Text(orderItem.item.name)
HStack {
Text("Quantity: \(orderItem.quantity)")
Spacer()
Stepper("", value: $orderItem.quantity)
}
}
}
}
}
}
}
This works with simple binding. Nice... But I'd like to implement a custom binding here, so that user cannot decrement quantity below zero.
That's where getting issues.
I tried replacing my stepper binding this way :
Stepper("", value: bindingForItemQuantity($oi))
private func bindingForItemQuantity(_ bindedOrderItem: Binding<OrderItem>) -> Binding<Int> {
let oi = bindedOrderItem.wrappedValue
return Binding<Int>(
get: { orderItem.quantity },
set: { newValue in
if newValue >= 1 {
orderItem.quantity = newValue
}
}
)
}
But i'm getting errors Cannot assign to property: 'orderItem' is a 'let' constant
I guess because my OrderItem is a struct, so i'll update it to be a class. But then my view is not automaticaly updating when using the steppers. I've been hacking it so it ended working (toggling a State bool in my Binding.set) but I guess i'm just going the wrong way...
What would be a clean binding solution here ?
Answer
Update your code with
private func bindingForItemQuantity(_ bindedOrderItem: Binding<OrderItem>) -> Binding<Int> {
return Binding<Int>(
get: { bindedOrderItem.quantity.wrappedValue },
set: { newValue in
print(newValue)
if newValue >= 1 {
bindedOrderItem.quantity.wrappedValue = newValue
}
}
)
}
Enjoyed this question?
Check out more content on our blog or follow us on social media.
Browse more questions