С @ObservedObject
все хорошо ... давайте проанализируем ...
Итерация 1:
Возьмите ваш код без изменений и добавьте только следующую строку ( показывает в виде текста текущее состояние visible
массива)
VStack { // << right below this
Text("\(numberLine.visible.reduce(into: "") { $0 += $1 ? "Y" : "N"} )")
и запуска, и вы видите, что Text
обновлен, так что наблюдаемый объект работает
![demo](https://i.stack.imgur.com/MvL8C.gif)
Итерация 2:
Удалите self.numberLine.objectWillChange.send()
и используйте вместо этого шаблон по умолчанию @Published
в представлении модели
class NumberLinex: ObservableObject {
@Published var visible: [Bool] = Array(repeatElement(true, count: 10))
}
запустите и вы увидите это обновление работает так же, как в первом демонстрационном примере выше.
* Но ... основные числа в ForEach
все еще не обновлены ... да, потому что проблема в ForEach
- вы использовали конструктор с Range
, который генерирует константу группу представления by-design (что задокументировано!).
!! Вот причина - вам нужны Dynami c ForEach
, но для этой модели необходимо изменить.
Итерация 3 - Финал:
Dynami c ForEach
Конструктор требует, чтобы итеративные элементы данных были идентифицируемыми, поэтому нам нужна struct как модель и обновленная модель представления.
Вот окончательное решение и демонстрация (протестировано с Xcode 11.4 / iOS 13.4)
![demo2](https://i.stack.imgur.com/mUIBn.gif)
struct ContentView: View {
@ObservedObject var numberLine = NumberLine()
var body: some View {
VStack {
HStack {
ForEach(numberLine.visible, id: \.id) { number in
Group {
if number.visible {
Text(String(number.id)).font(.title).padding(5)
}
}
}
}.padding()
Button("Change") {
let index = Int.random(in: 0 ..< self.numberLine.visible.count)
self.numberLine.visible[index].visible.toggle()
}.padding()
}
}
}
class NumberLine: ObservableObject {
@Published var visible: [NumberItem] = (0..<10).map { NumberItem(id: $0) }
}
struct NumberItem {
let id: Int
var visible = true
}