微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在同一个 View 中按 ID 加载不同的数据

如何解决在同一个 View 中按 ID 加载不同的数据

我想使用带索引的 ObservableObject 在同一个视图中加载不同的数据。

正如您在附加的简单演示示例中看到的那样,当我查看更改 id 的视图以加载其工作的不同数据时。

但是当我在任何时候从另一个可观察对象(在本例中为 AnotherObservable)更改另一个数据时,我的视图就会中断并且根本找不到任何数据。

导航有效...

Works

一旦我按下“更改标题”按钮...

Issue

要测试问题,只需简单地复制并粘贴代码并使用 浏览数据,然后按 更改标题 按钮

class DemoItemsLoader: ObservableObject {
    @Published var items = [1,2,3,4]
}

class DemoArticleLoader: ObservableObject {
    @Published var items = [1 : "One",2 : "Two",3 : "Three",4 : "Four"]
    @Published var realData: String?

    func loadItemForID(id: Int) {
        realData = items[id] ?? "Not found"
    }
}
class AnotherObservable: ObservableObject {
    @Published var title: String = "Title"
}


struct Class1: View {
    @StateObject var anotherObservable = AnotherObservable()
    @StateObject var itemsLoader = DemoItemsLoader()
    var body: some View {
        NavigationView{
            vstack {
                ForEach(itemsLoader.items,id: \.self) { item in
                    NavigationLink(
                        destination: Class2(anotherObservable: anotherObservable,articleLoader: DemoArticleLoader(),id: item)) {
                        Text("\(item)")
                    }
                }
            }
        }
    }
}

struct Class2: View {
    @Observedobject var anotherObservable: AnotherObservable
    @Observedobject var articleLoader: DemoArticleLoader
    @State var id: Int

    var body: some View {
        vstack {
            Text(anotherObservable.title)
            Text(articleLoader.realData ?? "Not found")
            HStack {
                Spacer()
                Button(action: {
                    if id > 1 {
                        id = id - 1
                        articleLoader.loadItemForID(id: id)
                    }
                }) {
                    Text("<-")
                }
                Button(action: {
                    if id < articleLoader.items.count {
                        id = id + 1
                        articleLoader.loadItemForID(id: id)
                    }

                }) {
                    Text("->")
                }
                Button(action: {
                    anotherObservable.title = "Another Title"
                }) {
                    Text("Change title")
                }
                Spacer()
            }
        }
        .onAppear { articleLoader.loadItemForID(id: id)}
    }
}

解决方法

问题是您仅在 loadItemForID 中调用 onAppear

.onAppear { articleLoader.loadItemForID(id: id)}

当你改变标题时,不会再次调用上述函数。

最简单的解决方案可能是将 DemoArticleLoader() 存储为 @StateObject,这样就不会每次都重新创建:

struct Class1: View {
    @StateObject var anotherObservable = AnotherObservable()
    @StateObject var itemsLoader = DemoItemsLoader()
    @StateObject var articleLoader = DemoArticleLoader() // create once

    var body: some View {
        NavigationView {
            VStack {
                ForEach(itemsLoader.items,id: \.self) { item in
                    NavigationLink(
                        // pass here
                        destination: Class2(anotherObservable: anotherObservable,articleLoader: articleLoader,id: item)) {
                        Text("\(item)")
                    }
                }
            }
        }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。