Pourquoi @Published met à jour le texte mais ne met pas à jour la liste?
Je ne comprends pas pourquoi les Text
mises à jour mais le List
ne le fait pas.
J'ai un modèle avec un @Published
qui est un tableau de dates. Il existe également une méthode pour générer du texte à partir des dates.
Voici une version simplifiée:
class DataModel: NSObject, ObservableObject {
@Published var selectedDates: [Date] = []
func summary() -> String {
var lines: [String] = []
for date in selectedDates.sorted().reversed() {
let l = "\(someOtherStuff) \(date.dateFormatted)"
lines.append(l)
}
return lines.joined(separator: "\n")
}
}
Et je montre ce texte à mon avis. Voici une version simplifiée:
struct DataView: View {
@ObservedObject var model: DataModel
var body: some View {
ScrollView {
Text(model.summary())
}
}
}
Cela fonctionne: lorsque l'utilisateur, à partir de l'interface utilisateur de la vue, ajoute une date à model.selectedDates
, le texte de résumé est correctement mis à jour.
Maintenant, je veux remplacer le texte par une liste de lignes.
Je change de méthode:
func summary() -> [String] {
var lines: [String] = []
for date in selectedDates.sorted().reversed() {
let l = "\(someOtherStuff) \(date.dateFormatted)"
lines.append(l)
}
return lines
}
Et changez la vue:
var body: some View {
ScrollView {
List {
ForEach(model.summary(), id: \.self) { line in
Text(line)
}
}
}
}
Mais cela ne fonctionne pas: il n'y a pas du tout de texte dans la liste, il n'est jamais mis à jour lorsque l'utilisateur ajoute une date à model.selectedDates
.
Qu'est-ce que je fais mal?
Réponses
J'ai pu trouver cette réponse à un article précédent sur SO qui peut être la solution à votre problème. Lorsque vous dites qu'il n'y avait aucun texte dans la liste, avez-vous débogué pour vérifier cela, ou n'y avait-il simplement aucune donnée affichée à l'écran?
Lorsque j'ai fait une copie de votre extrait de code et que je l'ai manipulé, il est apparu qu'il y avait en fait des données dans la liste que la liste tentait d'afficher à l'écran, mais le cadre de la liste était remplacé par le Scrollview. L'imbrication de tout à l'intérieur d'un GeometryReader et l'attribution d'une taille d'image à la liste ont donné au programme la fonctionnalité qu'il semble que vous recherchez.
Utilisez un ScrollView ou une liste pour vos données. Si une liste a plusieurs valeurs, elle se transforme automatiquement en une liste déroulante. Donc, je pense que vous pouvez simplement supprimer entièrement ScrollView.
Voici une variante de travail fixe (avec quelques réplications - vous devez donc l'adapter à votre projet).
Testé avec Xcode 12.1 / iOS 14.1
class DataModel: NSObject, ObservableObject {
@Published var selectedDates: [Date] = []
func summary() -> [String] {
var lines: [String] = []
for date in selectedDates.sorted().reversed() {
let l = "someOtherStuff \(date)"
lines.append(l)
}
return lines
}
}
struct DataView: View {
@ObservedObject var model: DateDataModel = DataModel()
var body: some View {
VStack {
Button("Add") { model.selectedDates.append(Date())}
List {
ForEach(model.summary(), id: \.self) { line in
Text(line)
}
}
}
}
}