i'm new in SwiftUI. So, I am doing my practice and create some kind of cashier app and here I been stuck for a while. In ProductPageView
I can increase and decrease the number of item. Then, when I go to DetailOrderView
(like a cart view), I can also increase and decrease the quantity number. The print shows the quantity number correctly. But if I go back to ProductPageView
, the label doesn't update it self.
Take a look at this screenshots:
First, I add 2 items.
Then I go to DetailOrderView
, the quantity number is the same.:
Then I add 2 items in DetailOrderView
(so it's now 4 items) and going back to ProductPageView
, notice how the total price has increased but the quantity doesn't change. I feel like I want to "refresh" or "reload data" on this page.
How can I fix this and update the Text when I press the back button?
Here's my code:
Main
import SwiftUI
@main
struct CashierApp: App {
@StateObject var productOder = ProductPresenter()
var body: some Scene {
WindowGroup {
MainPageView()
.environmentObject(productOder)
}
}
}
Product Page View import SwiftUI
struct ProductPageView: View {
@EnvironmentObject var productOrder: ProductPresenter
var body: some View {
VStack {
ScrollView {
VStack {
ForEach(productOrder.cartItems, id: \.item.idItem) { element in
ProductRow(cartItems: CartItems(item: element.item, quantity: element.quantity))
}
}
}
TotalPaymentRow()
}
}
}
Detail Order View or Cart View import SwiftUI
struct DetailOrderView: View {
@EnvironmentObject var productOrder: ProductPresenter
var arrayOrdered: [CartItems] = []
var body: some View {
ZStack {
ScrollView {
VStack {
ForEach(arrayOrdered, id: \.item.idItem) { element in
ProductRow(cartItems: CartItems(item: element.item, quantity: element.quantity))
}
}
.padding(.top, 10)
}
CustomModalGrandTotal()
}
.navigationTitle("Cart")
.navigationBarTitleDisplayMode(.inline)
}
}
The Presenter
import SwiftUI
import Combine
class ProductPresenter: ObservableObject {
@Published var cartItems: [CartItems] = []
var totalQuantity = 0
// Increment product
func increment(cartItem: inout CartItems) {
let index: Int = cartItems.firstIndex(where: {$0.item == cartItem.item}) ?? -1
cartItems[index].quantity += 1
totalQuantity += 1
}
// Decrement product
func decrement(cartItem: inout CartItems) {
let index: Int = cartItems.firstIndex(where: {$0.item == cartItem.item}) ?? -1
if cartItems[index].quantity > 0 {
cartItems[index].quantity -= 1
totalQuantity -= 1
}
}
}
Product Row
import SwiftUI
struct ProductRow: View {
@State var cartItems: CartItems
@EnvironmentObject var productOrder: ProductPresenter
var body: some View {
HStack(alignment: .center) {
Image(cartItems.item.image ?? "")
VStack(alignment: .leading, spacing: 8) {
Text(cartItems.item.name ?? "")
Text(getPrice(value: cartItems.item.price ?? 0))
}
Spacer()
VStack {
Spacer()
HStack{
Button(action: {
if cartItems.quantity > 0 {
cartItems.quantity -= 1
productOrder.decrement(cartItem: &cartItems)
productOrder.calculateTotalPrice()
}
}, label: {
imageMinusPlus(name: "minus")
})
Text("\(cartItems.quantity)") // This Text should be updated.
Button(action: {
cartItems.quantity += 1
productOrder.increment(cartItem: &cartItems)
productOrder.calculateTotalPrice()
}, label: {
imageMinusPlus(name: "plus")
})
}
}
}
}
}
PS: I deleted the styling to make the code shorter.
Thankyou in advance
Besides passing "ProductPresenter" instance around as "environment" object (which you are handling correctly) you need to declare your properties as @Published, as in this case for "totalQuantity", which now updates the total overall quantity.
class ProductPresenter: ObservableObject {
@Published var cartItems: [CartItems] = [
CartItems(item: CartItems.Item(image: "system.car", name: "My item", price: 10, idItem: UUID()), quantity: 3)
]
@Published var totalQuantity = 0
}
But this doesnt solve this line:
Text("\(cartItems.quantity)") // This Text should be updated.
for following reasons:
I think productOrder need to be defined as ObservableObject with @Published properties and int this case it need to be class not a structure, for example:
import SwiftUI
import Combine
final class ProductOder: ObservableObject {
@Published var cartItems: [CartItem] = []
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.