繁体   English   中英

SwiftUI iOS 14 视图不会使用 @EnvironmentObject 更新 @Published 数组

[英]SwiftUI iOS 14 View does not Update @Published Array with @EnvironmentObject

我正在开发卡路里跟踪器应用程序。 在我的应用程序中,我可以打开某些产品的详细信息侧,设置数量并将产品添加到“购物车”。 稍后,我想从数组中读出所有收集的数据,并向它们展示一个简短的概述。

但是在阵列上进行更改后,此视图不会更新。 由于我使用 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 视图更改为带有 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

我自己发现了这个错误。 问题是,我在.sheet操作中明确提交了一个 .environmentObject 。

AmountView(product: product).environmentObject(Cart())

我从.sheet操作中删除了.environmentObject(Cart()) 现在它正在工作。

认为这会导致错误,因为我在项目的主视图中使用.environmentObject(Cart())运算符。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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