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)")
    }
}
Другие вопросы по тегам