gpt4 book ai didi

ios - 列表行内的 SwiftUI @StateObject

转载 作者:行者123 更新时间:2023-12-04 15:12:50 27 4
gpt4 key购买 nike

SwiftUI 似乎不会为列表行保留 @StateObjects,当行嵌入容器(如堆栈或 NavigationLink)时。这是一个例子:

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 在 View 刷新时保持不变。

SwiftUI 在持久化 @StateObjects 时遵循什么规则?在此示例中,MyObject 可能正在存储重要的状态信息或下载远程 Assets - 那么我们如何确保每行只发生一次(与 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 inside 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)
}
}
}

关于ios - 列表行内的 SwiftUI @StateObject,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64882804/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com