SwiftUI iOS 14 视图不使用 @EnvironmentObject 更新 @Published 数组
Posted
技术标签:
【中文标题】SwiftUI iOS 14 视图不使用 @EnvironmentObject 更新 @Published 数组【英文标题】:SwiftUI iOS 14 View does not Update @Published Array with @EnvironmentObject 【发布时间】:2020-08-30 19:13:40 【问题描述】:我正在开发一个卡路里跟踪器应用程序。 在我的应用程序中,我可以打开一些产品的详细信息,设置数量并将产品添加到“购物车”。 稍后,我想从数组中读出所有收集到的数据,并给他们一个简短的概述。
但是在对数组进行更改后,此视图将不会更新。 由于我使用 userDefaults 存储数据,我总是必须重新打开应用程序来更新视图。只有这样,孔阵列才会显示出来。
我的课堂购物车:
import Foundation
struct Order: Equatable, Identifiable, Codable
var id = UUID()
var product: Product
var modifier: Double
var date: Date
class Cart: ObservableObject
@Published var orders = [Order]()
static let saveKey = "SavedData"
init()
if let data = UserDefaults.standard.data(forKey: Self.saveKey)
if let decoded = try? JSONDecoder().decode([Order].self, from: data)
self.orders = decoded
else
self.orders = []
// save order
func save()
if let encoded = try? JSONEncoder().encode(self.orders)
UserDefaults.standard.set(encoded, forKey: Self.saveKey)
// add to order
func add(order: Order)
self.orders.append(order)
print("product added to cart")
save()
// remove from order
func remove(order: Order)
if let index = orders.firstIndex(of: order)
orders.remove(at: index)
我做了一个视图来应用任何特殊产品的数量。
import SwiftUI
struct AmountView: View
@EnvironmentObject var cart: Cart
@State private var textInput = ""
@State private var orderFinished = false
var product: Product
func StringDoubleConverter(text: String) -> String
return String(format: "%.2f", Double(textInput.replacingOccurrences(of: ",", with: ".")) ?? 0)
var body: some View
VStack
Form
Section(header: Text("Mengenangabe"))
// input for the amount
AmountInputView(textInput: $textInput)
if !orderFinished
Button("Hinzufügen", action:
orderFinished = true
hideKeyboard()
// add product to the cart
self.cart.add(order: Order(product: product, modifier: Double(StringDoubleConverter(text: textInput))!, date: Date()))
)
.disabled(textInput == "")
.animation(.default)
else
Text("Wurde zum Logbuch hinzugefügt")
.foregroundColor(.blue)
productNutritionCollectionView(product: product, modifier: Double(StringDoubleConverter(text: textInput))!)
struct AmountView_Previews: PreviewProvider
static var previews: some View
AmountView(product: Product.exampleProduct).environmentObject(Cart())
然后,我想使用 Form 和 ForEach lope 在日志视图中按顺序显示所有产品。
struct LogbookView: View
func deleteProducts(at offsets: IndexSet)
cart.orders.remove(atOffsets: offsets)
cart.save()
@EnvironmentObject var cart: Cart
@State private var date = Date()
var body: some View
NavigationView
Form
Section(header: Text("List"))
ForEach(cart.orders) order in
Text(order.product.name)
.onDelete(perform: indexSet in
deleteProducts(at: indexSet)
)
.navigationBarTitle(Text("Logbuch"), displayMode: .automatic)
.navigationBarItems(trailing: DateView(date: $date))
struct LogbookView_Previews: PreviewProvider
static var previews: some View
LogbookView().environmentObject(Cart())
我正在使用 AppTab 视图来导航应用程序。因此,我将主 Struct 中的 AppTab View 更改为默认 View,环境对象为 Cart。
@main
struct KalorientrackerApp: App
var body: some Scene
WindowGroup
AppTabView().environmentObject(Cart())
struct KalorientrackerApp_Previews: PreviewProvider
static var previews: some View
Text("Hello, World!")
我正在使用 .sheet 打开我的 AmountView
struct ProductDetailView: View
@State private var showAmountView = false
let product: Product
var body: some View
VStack
// placeholder Image
Image(product.fullImage)
.clipShape(Circle())
.padding(.top, 5)
Spacer()
Form
productNutritionCollectionView(product: product, modifier: 100)
// Titel for Navigation bar
.navigationBarTitle(Text(product.name), displayMode: .inline)
// Button to go to amount view
.navigationBarItems(trailing: Button(action:
self.showAmountView = true
, label:
Image(systemName: "plus.circle")
.padding(.leading, 20)
).sheet(isPresented: $showAmountView, content:
AmountView(product: product).environmentObject(Cart())
))
struct ProductDetailView_Previews: PreviewProvider
static var previews: some View
ProductDetailView(product: Product.exampleProduct)
我已经找到了一些其他的讨论,但它们对我没有用。
我正在使用 Xcode 12 beta 6 和 ios14 beta 6
【问题讨论】:
您是否在 SceneDelegate 中添加了您的环境变量? window.rootViewController = UIHostingController(rootView: contentView.environmentObject(Cart())) 然后初始化你的 Cart 类加载 UserDefaults SceneDelegate 在 Xcode12 中不再可用。这是一个在 Xcode 测试版中制作的新项目。我将购物车添加到 @main 结构中。 据我所知,您没有提供代码的问题部分。你会展示你创建购物车的部分,你如何列出订单,你如何创建工作表......还是我们应该猜测? 对不起。将缺失的代码添加到问题中。 我遇到了类似的问题。这篇文章为我解决了这个问题:***.com/questions/57615920/… 【参考方案1】:我自己发现了这个错误。问题是,我在.sheet
操作中明确提交了一个 .environmentObject。
AmountView(product: product).environmentObject(Cart())
我从.sheet
操作中删除了.environmentObject(Cart())
。现在它正在工作。
认为这会导致错误,因为我在项目的主视图中使用了 .environmentObject(Cart())
运算符。
【讨论】:
以上是关于SwiftUI iOS 14 视图不使用 @EnvironmentObject 更新 @Published 数组的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI禁止用户关闭sheet弹出视图在iOS14.6+失效的巧妙解决