【问题标题】:Updating EnvironmentObject in child view causes view to pop在子视图中更新 EnvironmentObject 会导致视图弹出
【发布时间】:2021-08-23 00:04:49
【问题描述】:

我有一个更新 EnvironmentObject 的子视图,然后导致子视图弹回其父视图。我正在创建一个使用本教程中类似“Like”功能的应用程序:https://www.hackingwithswift.com/books/ios-swiftui/letting-the-user-mark-favorites

每次单击赞按钮并更新 EnvironmentObject 赞对象时,视图都会弹出到前一个 (ProductGridView) 视图,而不是停留在子视图 (ProductDetailView) 上。

struct ContentView: View {
@State private var tabSelection = 0
@ObservedObject var products = Products()
@ObservedObject var favorites = Favorites()

var body: some View {
    VStack {
        TabView(selection: $tabSelection) {
            NavigationView{
                ProductGridView()
            }
            .tabItem { Image(systemName: "megaphone")
                Text("Products")
            }.tag(0)
             .environmentObject(products)
             .environmentObject(favorites)
     }


struct ProductGridView: View {
var columns: [GridItem] = Array(repeating: .init(.flexible()), count: 2)
@EnvironmentObject var products: Products
@EnvironmentObject var favorites: Favorites
var body: some View {
    VStack{
            ScrollView(.vertical,  showsIndicators: false) {
                LazyVGrid(columns: columns, alignment: .leading, spacing: 20) {
                        ForEach(products.products, content: {
                            product in
                            NavigationLink(destination: ProductDetailView(product: product)) {
                                ProductCellView(product: product)
                                    .padding(.horizontal, 10)
                            }
                        })
                    }
                }.onAppear() {
                    self.products.fetchData()
                }
            }

struct ProductDetailView: View {
    let product: Product
    @EnvironmentObject var favorites: Favorites
    var body: some View {
        ScrollView(showsIndicators: false) {
            VStack{
                ProductImageView(product: product)
                        Button(action: {
                            if favorites.contains(product) {
                                favorites.remove(product) //Updating here causes issue
                            } else {
                                favorites.add(product) //Updating here causes issue
                            }
                        }) {
                            if favorites.contains(product){
                                Image(systemName: "heart.fill")
                            }
                            else{
                                Image(systemName: "heart")
                            }
                        }
                    }

class Favorite : Identifiable, Encodable {
    var id = UUID()
    var name: String
...

class Favorites: ObservableObject {
    @Published private var products: [String]?
...

struct Product: Identifiable{
    let id = UUID()
    let productname: String
...

【问题讨论】:

  • 我可能不会以这种方式构建我的模型。使用 @Published 产品和收藏夹创建单个 ObservableObject。将此模型的实例注入到视图层次结构之外的环境中(例如ContentView().environmentObject(MyModel)
  • 一些观察,在 ContentView 中使用@StateObject 而不是@ObservedObject。这是您正在使用的真实代码还是一些半复制和粘贴工作。我看到了您没有显示的“ProductView()”,您是否在 ContentView 中声明了“ProductGridView”?
  • 还显示products.products(假定为Product)的内容如何符合identifiable - Favorites 相同
  • 我更新了问题。我只是复制部分代码。
  • so Favorites 是一个类而不是一个结构体,还是另外一半复制粘贴?

标签: ios swift swiftui


【解决方案1】:

看起来您的 fetch data 调用可能会导致问题。

struct YourContentView: View {
    @State private var tabSelection = 0
    @ObservedObject var products = Products()
    @ObservedObject var favorites = Favorites()
    
    var body: some View {
        VStack {
            TabView(selection: $tabSelection) {
                NavigationView{
                    ProductGridView()
                }
                .tabItem { Image(systemName: "megaphone")
                    Text("Products")
                }.tag(0)
                .environmentObject(products)
                .environmentObject(favorites)
            }
        }
    }
    
}

struct ProductDetailView: View {
    let product: Product
    @EnvironmentObject var favorites: Favorites
    
    var body: some View {
        ScrollView(showsIndicators: false) {
            VStack{
                Image(systemName: "photo")
                    .resizable()
                    .scaledToFit()
                
                Button {
                    if favorites.products?.contains(product) ?? false {
                        favorites.remove(product) //Updating here causes issue
                    } else {
                        favorites.add(product) //Updating here causes issue
                    }
                } label: {
                    if favorites.products?.contains(product) ?? false{
                        Image(systemName: "heart.fill")
                    }
                    else{
                        Image(systemName: "heart")
                    }
                }
            }
        }
    }
}

struct ProductCellView: View {
    @State var product: Product
    
    var body: some View {
        HStack {
            Image(systemName: "photo")
            Text(product.productname)
        }
    }
}


struct ProductGridView: View {
    let columns: [GridItem] = Array(repeating: .init(.flexible()), count: 2)
    @EnvironmentObject var products: Products
    @EnvironmentObject var favorites: Favorites

    var body: some View {
        VStack{
            ScrollView(.vertical,  showsIndicators: false) {
                LazyVGrid(columns: columns, alignment: .leading, spacing: 20) {
                    ForEach(products.products, content: {
                        product in
                      
                        NavigationLink(destination: ProductDetailView(product: product)) {
                            ProductCellView(product: product)
                                .padding(.horizontal, 10)
                        }
                    })
                }
            }.onAppear() {
                self.products.fetchData()
            }
        }
    }
}

class Favorites: ObservableObject {
    @Published var products: [Product]? = []
  
    init() {}
    
    func remove(_ product: Product) {
        products?.removeAll(where: { $0.id == product.id })
    }
    
    func add(_ product: Product) {
        products?.append(product)
    }
}

class Products: ObservableObject, Identifiable {
    @Published var products: [Product]
    
    init() {
        products = [.init(productname: "ApplePie"), .init( productname: "Cheeseburger")]
    }
   
    func fetchData() {
//        uncommenting this code will cause product grid view to reload because it relies on products
//        products = [.init(productname: "ApplePie"), .init( productname: "Cheeseburger")]
    }
}



struct Product: Identifiable, Equatable {
    let id = UUID()
    let productname: String

    public static func ==(lhs: Product, rhs: Product) -> Bool {
        lhs.id == rhs.id
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-03
    • 2020-03-06
    • 1970-01-01
    • 1970-01-01
    • 2022-10-15
    • 1970-01-01
    • 2012-11-18
    相关资源
    最近更新 更多