SwiftUI @Published и @ObservedObject не переходят в пункт назначения NavigationLink
Извините за название и длину, которые я изо всех сил старался сократить
У меня есть класс данных @ObserableObject @Published, которые я хочу изменить и использовать новые данные на второй странице, доступной через NavigationLink
class Data: ObservableObject {
@Published var number = 5
var correctNumber: Int {
number + 1
}
}
Затем у меня есть средство выбора, чтобы выбрать / изменить номер
Picker("What times tables do you want to test your knowledge on?", selection: $data.number) {
ForEach(0 ..< data.numberRange.count) {
Text("\(self.data.numberRange[$0])")
}
}
Это работает так, как ожидалось, когда у меня текст показывает исправленный номер на главном экране и изменяется / обновляется при изменении средства выбора
Text ("Number = \(data.correctNumber)")
Затем я перехожу на второй экран с помощью NavigationLink
NavigationLink(destination: QuestionView()) {
Text("Start")
}
На втором экране я установил @ObservedObject и снова отобразил текст.
struct QuestionView: View {
@ObservedObject var data = Data()
var body: some View {
Text("Number = \(self.data.correctNumber)")
}
При нажатии кнопки Старт отображается только число как 5 + 1, а не число, на которое оно было изменено с помощью средства выбора.
Я пытался;
- Не использовать себя. но заметной разницы не было
- При переключении на привязку $ возникли следующие проблемы; Невозможно присвоить свойству: "rightNumber" является свойством только для получения, а метод экземпляра "appendInterpolation" требует, чтобы "привязка" соответствовала "_FormatSpecifiable"
- Добавление @Published в correNumber, но я не могу добавить это в вычисленное состояние
Теперь у меня нет идей, может ли кто-нибудь помочь нубу, пожалуйста
PS Прошу прощения, если терминология неверна, не стесняйтесь поправлять меня, чтобы я учился в следующий раз
2 ответа
Все остальные ответы верны. Вам нужно будет выбрать то, что лучше всего подходит для вашего сценария.
Я считаю, что тебе не нужен @EnvironmentObject
(он станет глобально доступным для всех ваших представлений в иерархии). И передачи просто числа сейчас может быть достаточно, но оно не масштабируется (что, если вы хотите использовать другое свойствоData
в QuestionView
?).
Я рекомендую передать Data
объект, но как @ObservedObject:
NavigationLink(destination: QuestionView(data: data)) {
Text("Start")
}
struct QuestionView: View {
@ObservedObject var data: Data
var body: some View {
Text("Number = \(self.data.correctNumber)")
}
}
Таким образом, изменения в вашем коде будут минимальными. И если вы планируете использоватьcorrectNumber
в QuestionView
только - вы можете безопасно переместить его туда *, как предлагается в другом ответе).
Вы снова инициализируете наблюдаемый объект Data, поэтому на самом деле ожидается, что представление всегда будет отображать 5 + 1.
На мой взгляд, в данном случае вам действительно не нужно свойство компьютера, так что вы можете отказаться от него. Мое предложение вместо этого передать свойство number как привязку и просто отобразить его с увеличением на 1 в вашем QuestionView. Другим подходом было бы переместить вычисленное свойство rightNumber внутрь вашего QuestionView, но при этом передать свойство number как привязку.
Вот как эти сценарии будут выглядеть в вашем случае:
- Непосредственное отображение значения, увеличенного на 1
class Data: ObservableObject {
@Published var number = 5
}
NavigationLink(destination: QuestionView(number: $data.number)) {
Text("Start")
}
struct QuestionView: View {
@Binding var number : Int
var body: some View {
Text("Number = \(self.number + 1)")
}
}
- и очень похоже, если вы решите переместить вычисляемое свойство, просто измените текстовое поле QuestionView, чтобы использовать его вместо этого:
struct QuestionView: View {
@Binding var number : Int
var correctNumber: Int {
self.number + 1
}
var body: some View {
Text("Number = \(self.correctNumber)")
}
}