无法使用@EnvironmentObject SwiftUI 更新先前视图上的文本
Posted
技术标签:
【中文标题】无法使用@EnvironmentObject SwiftUI 更新先前视图上的文本【英文标题】:Can't Update Text on Previous View using @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 个数量过滤它以显示在购物车视图中。当我在购物车视图中 + 或 - 该产品并返回上一页(产品页面)时,它不会更新文本。虽然实际在后台,但打印值是正确的
【参考方案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: Item
和var 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
。
是的,需要初始化为空数组
是的,我已经将它初始化为一个空数组。检查我更新的代码以上是关于无法使用@EnvironmentObject SwiftUI 更新先前视图上的文本的主要内容,如果未能解决你的问题,请参考以下文章
View.environmentObject(_:) 作为该视图的祖先可能会丢失——但并非总是如此……
SwiftUI - 在 ObservableObject 类/依赖注入中使用 EnvironmentObject
在 watchOS 中使用 environmentObject