【问题标题】:Can't Update Text on Previous View using @EnvironmentObject SwiftUI无法使用@EnvironmentObject SwiftUI 更新先前视图上的文本
【发布时间】:2021-03-12 05:57:11
【问题描述】:

我是 SwiftUI 的新手。所以,我正在练习并创建某种收银应用程序,在这里我被困了一段时间。在ProductPageView 我可以增加和减少项目的数量。然后,当我去DetailOrderView(就像购物车视图)时,我也可以增加和减少数量。印刷品正确显示数量。 但如果我回到ProductPageView,标签不会自行更新。

看看这个截图:

首先,我添加 2 个项目。

那我去DetailOrderView,数量一样。:

然后我在DetailOrderView 中添加 2 件商品(所以现在是 4 件商品)并返回到 ProductPageView,请注意总价格如何增加但数量没有变化。我觉得我想在此页面上“刷新”或“重新加载数据”。

当我按下返回按钮时,如何解决这个问题并更新文本?

这是我的代码:

主要

import SwiftUI

@main
struct CashierApp: App {
    @StateObject var productOder = ProductPresenter()

var body: some Scene {
    WindowGroup {
        MainPageView()
            .environmentObject(productOder)
    }
}

}

产品页面查看 导入 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()
    }
}

}

详细订单视图或购物车视图 导入 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)
}

}

演示者

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

产品行

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:我删除了样式以使代码更短。

提前谢谢你

【问题讨论】:

  • 据我了解,您复制了您的 CarItems,并且您在每个视图中都使用了副本。将该模型数组移动到 ProductPresenter 并使其可观察,然后在该位置使用它。
  • totalQuantity 应该是@Published
  • @jnpdx , totalQuantity 不是显示数量的,它是统计总数量并检查购物车中是否有商品。显示每个产品数量的是cartItems.quantity。不过谢谢回答,我也试过了,还是不行
  • @Asperi ,是的,我使用的是同一行,但我用超过 0 个数量过滤它以显示在购物车视图中。当我在购物车视图中 + 或 - 该产品并返回上一页(产品页面)时,它不会更新文本。虽然实际在后台,但打印值是正确的

标签: ios swift swiftui state environmentobject


【解决方案1】:

除了将“ProductPresenter”实例作为“环境”对象(您正在正确处理)传递之外,您还需要将您的属性声明为@Published,例如“totalQuantity”,它现在会更新总量。

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 
}

但这并不能解决这一行:

Text("\(cartItems.quantity)") // This Text should be updated.

出于以下原因:

  • 您的模型 (CartItems) 必须是类类型并符合 ObservableObject 协议
  • 您的属性必须使用@Published 设置。

【讨论】:

  • 是的,我的CartItems 是一个由var item: Itemvar quantity: Int 组成的结构模型。这是必须要上课的吗?由于这是一个结构模型,如何将其更改为类?
  • 基本上你必须拥有一个可以为你做这件事的类对象。在这里,我制作了一个演示应用程序,为您服务。 github.com/svoip/ProductAdd
  • 它完全有效,感谢您的演示应用程序兄弟。你拯救了我的一天。
【解决方案2】:

我认为 productOrder 需要定义为具有 @Published 属性的 ObservableObject 并且在这种情况下它需要是类而不是结构,例如:

import SwiftUI
import Combine

final class ProductOder: ObservableObject {
    @Published var cartItems: [CartItem] = []
    
}

【讨论】:

  • 对不起,我忘记包含cartItems 的数组,而您的意思是cartItems= [] 对吗?检查我更新的Presenter
  • 是的,需要初始化为空数组
  • 是的,我已经将它初始化为一个空数组。检查我更新的代码
猜你喜欢
  • 1970-01-01
  • 2020-03-06
  • 1970-01-01
  • 1970-01-01
  • 2020-03-28
  • 2020-09-27
  • 2021-11-04
  • 1970-01-01
  • 2022-08-03
相关资源
最近更新 更多