【问题标题】:Load different data by ID in the same View在同一个View中按ID加载不同的数据
【发布时间】:2021-01-14 17:20:25
【问题描述】:

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

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

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

导航工作...

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

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

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)}
    }
}

【问题讨论】:

    标签: swift swiftui swiftui-navigationlink observableobject


    【解决方案1】:

    问题是您只在onAppear 中调用loadItemForID

    .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)")
                        }
                    }
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多