观察到的对象无意中被解雇 SwiftUI

Posted

技术标签:

【中文标题】观察到的对象无意中被解雇 SwiftUI【英文标题】:Observed Object gets Dismissed Unintentionally SwiftUI 【发布时间】:2021-10-13 07:38:58 【问题描述】:

我在 NavigationView 中有一个 HStack,其设计如下:

    用户可以滚动,然后点击 HStack 列表中的项目以查看详细信息 在详细视图中,用户可以选择项目 如果项目被选中,我将所选项目的新视图放在 HStack 顶部,因此只有所选项目可见 我想保留原始 HStack 并在新视图下方列出,以便用户可以反转流程而不会丢失滚动位置

我已经使用一些测试数据完成了这项工作,并且它按预期工作,但是当我使用来自 Firebase 调用的数据时,当新的“选定”视图置于顶部时,原始 HStack/List 视图将被关闭......我不明白为什么。我认为这可能与观察对象的启动方式有关。感谢您的帮助!

struct TestView: View 
@StateObject var selectedItem = SelectedItem()

//Real Query
@ObservedObject var query = Query()

@ObservedObject var testQuery = TestQuery()

var body: some View 
    VStack
        ZStack
            ScrollView(.horizontal) 
                HStack(spacing: 35) 

                    //ForEach(query.queriedList) doesn't work, however the below does...

                    ForEach(testQuery.testList)  menuItems in
                        NavigationLink(
                            destination: NewDetailView(selectedItem: selectedItem, weeklyItems: weeklyItems, menuItem: menuItems)) 
                            MenuItemView(menuItem: menuItems)
                                .padding([.leading, .trailing])
                        
                    
                
            
            //if the array is NOT empty
            if selectedItem.selection.isEmpty == false 
                
                //PUT THIS ON TOP
                ScrollView(.horizontal) 
                    NavigationLink(
                        destination: NewDetailView(selectedItem: selectedItem, weeklyItems: weeklyItems, menuItem: self.selectedItem.selection[0], isSelected: true)) 
                            MenuItemView(menuItem: self.selectedItem.selection[0])
                            .padding([.leading, .trailing])
                    
                
            
        
    

测试查询是什么样子的

class TestQuery: ObservableObject 

@Published var testList: [MenuItem] = [.init(title: "Ham & Eggs", prepTime: 5, cookTime: 5, rating: 2, lastUsed: 13), .init(title: "Hot Totters", prepTime: 5, cookTime: 5, rating: 2, lastUsed: 13), .init(title: "Ranch Dressing Soup", prepTime: 5, cookTime: 5, rating: 2, lastUsed: 13)]

Firebase 查询

class Query: ObservableObject 

@Published var queriedList: [MenuItem] = []

init() 
    baseQuery()


func baseQuery() 
  let queryRef1 = Firestore.firestore().collection("menuItems").limit(to: 50)
    print("base fired")
    queryRef1
        .getDocuments()  (querySnapshot, err) in
        if let err = err 
            print("Error getting documents: \(err)")
         else 
            self.queriedList = querySnapshot?.documents.compactMap  document in
                try? document.data(as: MenuItem.self)
                
             ?? []
        
    

【问题讨论】:

将观察到的两个对象改为状态对象 谢谢!很难相信我花了尽可能多的时间来努力解决这个问题。感谢您指出这一点。随意发布答案,我会接受。 【参考方案1】:

在 SwiftUI 视图中创建 ObservableObject 的唯一安全方法是使用

@StateObject

将两个 ObservedObjects 切换为 StateObjects

https://developer.apple.com/documentation/swiftui/managing-model-data-in-your-app

【讨论】:

以上是关于观察到的对象无意中被解雇 SwiftUI的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI 从另一个视图更改观察到的对象

在模板中使用异步管道可观察到的不适用于单个值

美团90%会被问到的问题设计模式之观察者模式

C++:对象、对对象的引用、对带有和不带有函数的向量元素的引用——观察到的性能差异

UIMenuController在被呈现后立即被解雇

项目中用到的设计模式-观察者模式