Как добавить элемент в глобальный список var initted / завернутый в ObservableObject в родительском представлении и отразить его в ForEach в SwiftUI в дочернем представлении?

#ios #swift #swiftui

#iOS #swift #swiftui

Вопрос:

Когда я нажимаю кнопку в contentView.swift, я ожидаю, что действие, вызывающее «добавление» к спортивному списку, покажет недавно добавленный элемент .. но это не так. Ошибок компиляции нет. Нажатие на кнопку ничего не делает (хотя я вижу, что SportItem упакован правильно) в инструкции print.

Я создал модель для элемента «SportItem», который имеет простые свойства (например, name: String) и класс ObservableObject.

 struct SportItem: Identifiable {
    let name: String
}
 

Затем я создаю глобальную переменную sportData и класс ObservableObject вне всего:

 var sportData = [
    SportItem(name: "Tennis"),
    SportItem(name: "Basketball")
]

class SportList: ObservableObject {
    @Published var sportList: [SportItem]
    init() {
        self.sportList = sportData 
    }
}
 

В SportListView.swift у меня есть внутри тела:

 @ObservedObject var sportList: SportList = SportList();

...
ForEach(sportList.sportList) {
    sport in 
    VStack(alignment: .leading) {
      Text(sport.name)
    }
}
 

Ссылка на SportListView содержится в contentView.swift, который имеет:

 var sportList:[SportItem] = sportItems
 

этот SportList (), используя:

 SportListView(sportList: SportList())
 

У меня также есть кнопка в родительском файле contentView.swift, где у меня есть кнопка, действие которой выполняет:

 SportList().sportData.append(SportItem(name: "Soccer"))
 

Когда я нажимаю на эту кнопку, я замечаю, что SportListView в симуляторе не добавляет новый элемент. Как мне обновить список, чтобы показать «Футбол», добавленный в список?

Комментарии:

1. Глобальные переменные не обновляют представление SwiftUI. Вам нужно обернуть sportData в модель представления, следуя ObservableObject / ObservedObject .

2. Я попытался обернуть ObservableObject / Observed object в OP, но все равно ведет себя не так, как я ожидал. Не могли бы вы проверить правильность упаковки или опубликовать ответ, который помог бы внести ясность?

Ответ №1:

Вы должны хранить sportData внутри SportList (при необходимости через общий экземпляр), например

 class SportList: ObservableObject {
    static let shared = SportList()

    @Published var sportData: [SportItem] = [ SportItem(name: "Tennis"), SportItem(name: "Basketball") ]
}
 

а затем

 @ObservedObject var sportList: SportList = SportList.shared
...
ForEach(sportList.sportData) {
sport in 
   VStack(alignment: .leading) {
     Text(sport.name)
   }
}
 

и добавить like (если он находится где-то вне поля зрения)

 SportList.shared.sportData.append(SportItem(name: "Soccer"))