SwiftUI:视图没有完全更新,当它的@ObservedObject 从父级更新时滞后?

SwiftUI: View does not fully update, lags behind when its @ObservedObject is updated from parent?

我有以下代码:

struct ContentView: View {
    
    @Environment(\.managedObjectContext) private var viewContext
    
    @State var selectedItemMOID:NSManagedObjectID?
    
    var body: some View {
        
        NavigationView {
            
            VStack {
                if let selectedItemMOID = selectedItemMOID, let item = viewContext.object(with: selectedItemMOID) as? Item {
                    ItemView(item: item)
                }
            }
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button {
                        if let item = addItem() {
                            selectedItemMOID = item.objectID
                        }
                    } label: {
                        Image(systemName: "plus")
                            .font(.system(size: 14, weight: .bold))
                    }
                }
            }
        }
    }
    
    private func addItem() -> Item? {
        withAnimation {
            let newItem = Item(context: viewContext)
            newItem.timestamp = Date()
            do {
                try viewContext.save()
                return newItem
            } catch {
                return nil
            }
        }
    }
    
}





struct ItemView: View {
    
    @ObservedObject var item:Item
    @State var itemIDString:String = ""
    
    var body: some View {
        
        List {
            
            VStack {
                
                Text(itemIDString)
                
                Text("the item: \(item.objectID)")
                
            }
            .onChange(of: item, perform: { newValue in
                updateIdString()
            })
            .onAppear {
                updateIdString()
            }
            
        }
        
    }
    
    func updateIdString() {
        
        itemIDString = "\(item.objectID)"
    }
    
    
}

问题:

当我按下加号按钮(右上角)时,ItemView 部分 更新。底部的文本视图立即更新,顶部的滞后。

看到这个行为:

你可以看到顶部的项目 id 总是落后一个(第一次渲染除外)。 因此,例如,点击加号(第一次之后),顶部是 p45,底部是 p46。等等。

为什么置顶文字落后一位?

我也添加了 onChange,以为可以同步,但没有。没有它,设置第一项后顶部文本永远不会更新。

    .onChange(of: item, perform: { newValue in
        updateIdString()
    })

我需要了解为什么会发生这种情况,这样我才能理解如何正确构建通常使用 @ObservedObject 的视图,以便在将 ObservedObject 设置为新视图时立即更新。

所以,要明确我的问题是如何修复此代码,以便在设置 item 时整个 ItemView 立即更新,以及 为什么会这样 处于较高水平,这样我就可以避免以后出现同样类型的错误。

解决 Asperi 的 方法(感谢您的回答!):

他的回答解决了这个具体案例,但是,我不确定我将如何使用该模式。例如,如果 ItemView 观察到多个对象,比如说一个 Car 和一个 User 实体,那么 .id(car.id) 只会对在 [ 上设置一个新的 Car 做出反应=12=] 而不是对设置新的 User 做出必要的反应。那么,在这种情况下,@ObservedObject 的意义何在?使用建议的 .id(car.id) 它只会对一个而不是另一个做出反应(如果 ItemView 有 6 个 @ObservedObjects... 则更多)。

这是否意味着一个视图应该只有一个@ObservedObject?我不这么认为。我错了吗?

只是想了解如何扩展 id(item.id) 模式(如果它是令人满意的答案)。还没看懂

我觉得是由于reuse/caching,总之渲染优化,试试

    List {
       // content is here
    }
    .id(item)     // << this one !!

因为你没有使用newValue,改成:

.onChange(of: item, perform: { newValue in
    itemIDString = "\(newValue.objectID)"
})