[英]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 的方法(感謝您的回答:):
他的回答修復了這個特定案例,但是,我不確定我將如何使用該模式 go 。 例如,如果ItemView
觀察到多個對象,比如說一個Car
和一個User
實體,那么.id(car.id)
只會對在ItemView
上設置新Car
做出反應,而不會對設置新User
做出必要的反應。 那么,在這種情況下, @ObservedObject
的意義何在。 使用建議的.id(car.id)
它只會對一個而不是另一個做出反應(如果ItemView
有 6 個 @ObservedObjects...,則更多)。
這是否意味着一個視圖應該只有一個@ObservedObject? 我不這么認為。 我錯了嗎?
只是想了解如何擴展id(item.id)
模式,如果它是令人滿意的答案。 我還不明白。
我認為這是由於重用/緩存,簡而言之渲染優化,嘗試
List {
// content is here
}
.id(item) // << this one !!
是因為你沒有使用newValue,改成:
.onChange(of: item, perform: { newValue in
itemIDString = "\(newValue.objectID)"
})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.