#swift #swiftui #swiftui-navigationlink #observableobject
#swift #свифтуи #swiftui-navigationlink #observableobject
Вопрос:
Я хочу загрузить разные данные в одно и то же представление, используя ObservableObject с индексом.
Как вы можете видеть в простом демонстрационном примере, прилагаемом, когда я просматриваю представления, меняя идентификатор, чтобы загрузить разные данные, это работает.
Но когда в какой-либо момент я изменяю другие данные из другого наблюдаемого объекта (в данном случае 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)}
}
}
Ответ №1:
Проблема в том, что вы звоните loadItemForID
onAppear
только:
.onAppear { articleLoader.loadItemForID(id: id)}
И когда вы меняете заголовок, вышеупомянутая функция больше не вызывается.
Вероятно, самым простым решением является сохранение DemoArticleLoader()
как a @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)")
}
}
}
}
}
}