ios - 在子视图中更新 EnvironmentObject 会导致视图弹出
问题描述
我有一个更新 EnvironmentObject 的子视图,然后导致子视图弹回其父视图。我正在创建一个使用本教程中类似“喜欢”功能的应用程序: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
...
解决方案
看起来您的 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
}
}
推荐阅读
- c++ - Boost asio 截止时间计时器立即完成(C++)
- javascript - 使用c#的无效表达式术语'['
- c# - 具有泛型参数的泛型方法
- redis - 我们可以将大量对象存储到 Redis 中吗?
- python - 有没有办法让这个 API 调用更快?
- wix - 如何在 wix 安装程序完成对话框中添加按钮
- android - 无法为按钮设置自定义字体
- django - Django inspectdb ORA-00942: 表或视图不存在
- camunda - 在 Camunda 中添加到任务列表导航栏的链接
- javascript - 如何在javascript中对json数据应用递归函数