在同一个View中通过ID加载不同的数据
Load different data by ID in the same View
我想使用带索引的 ObservableObject 在同一个视图中加载不同的数据。
正如您在所附的简单演示示例中看到的那样,当我通过更改 id 的视图以加载不同的数据时它起作用了。
但是,当我在任何时候更改另一个可观察对象 object 的另一个数据(在本例中为 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)}
}
}
问题是您只在 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)")
}
}
}
}
}
}
我想使用带索引的 ObservableObject 在同一个视图中加载不同的数据。
正如您在所附的简单演示示例中看到的那样,当我通过更改 id 的视图以加载不同的数据时它起作用了。
但是,当我在任何时候更改另一个可观察对象 object 的另一个数据(在本例中为 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)}
}
}
问题是您只在 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)")
}
}
}
}
}
}