![](/img/trans.png)
[英]SwiftUI animation problem with a binding to a StateObject inside a NavigationView
[英]SwiftUI @StateObject inside List rows
當行嵌入到容器(如堆棧或NavigationLink
時,SwiftUI 似乎不會為列表行保留@StateObjects
。 下面是一個例子:
class MyObject: ObservableObject {
init() { print("INIT") }
}
struct ListView: View {
var body: some View {
List(0..<40) { _ in
NavigationLink(destination: Text("Dest")) {
ListRow()
}
}
}
}
struct ListRow: View {
@StateObject var obj = MyObject()
var body: some View {
Text("Row")
}
}
當您向下滾動列表時,您會看到為出現的每個新行記錄了"INIT"
。 但是向上滾動,您會看到每一行都再次記錄了"INIT"
——即使它們已經出現了。
現在刪除NavigationLink
:
List(0..<40) { _ in
ListRow()
}
並且@StateObject
行為符合預期:每一行只有一個"INIT"
,沒有重復。 ObservableObject
在視圖刷新時保持不變。
SwiftUI 在持久化@StateObjects
時遵循什么規則? 在這個例子中, MyObject
可能正在存儲重要的狀態信息或下載遠程資產 - 那么我們如何確保它對每一行只發生一次(當與NavigationLink
等結合時)?
以下是有關StateObject
文檔說明:
/// @StateObject var model = DataModel()
///
/// SwiftUI creates a new instance of the object only once for each instance of
/// the structure that declares the object.
並且List
確實不會創建新的行實例,而是重用之前創建的並離開屏幕。 但是NavigationLink
每次都會為標簽創建新實例,因此您會看到這一點。
您的情況可能的解決方案是將NavigationLink
移動到ListRow
:
struct ListView: View {
var body: some View {
List(0..<40) { _ in
ListRow()
}
}
}
和
struct ListRow: View {
@StateObject var obj = MyObject()
var body: some View {
NavigationLink(destination: Text("Dest")) { // << here !!
Text("Row")
}
}
}
如果您想在沒有導航的情況下在某處重用ListRow
,您甚至可以將它們分開
struct LinkListRow: View {
@StateObject var obj = MyObject()
var body: some View {
NavigationLink(destination: Text("Dest")) {
ListRow(obj: obj)
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.