简体   繁体   中英

Can't Update Text on Previous View using @EnvironmentObject SwiftUI

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:

  • your model (CartItems) has to be a class type and conform to ObservableObject protocol
  • your property has to be set using @Published.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM