Warum @Published aktualisiert Text, aktualisiert Liste jedoch nicht?
Ich verstehe nicht, warum die Text
Updates, aber das List
nicht.
Ich habe ein Modell mit einem, @Published
das eine Reihe von Daten ist. Es gibt auch eine Methode, um Text aus den Daten zu generieren.
Hier ist eine vereinfachte Version:
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")
}
}
Und ich zeige diesen Text aus meiner Sicht. Hier ist eine vereinfachte Version:
struct DataView: View {
@ObservedObject var model: DataModel
var body: some View {
ScrollView {
Text(model.summary())
}
}
}
Es funktioniert: Wenn der Benutzer über die Benutzeroberfläche in der Ansicht ein Datum hinzufügt model.selectedDates
, wird der Zusammenfassungstext ordnungsgemäß angepasst.
Jetzt möchte ich den Text durch eine Zeilenliste ersetzen.
Ich ändere die Methode:
func summary() -> [String] {
var lines: [String] = []
for date in selectedDates.sorted().reversed() {
let l = "\(someOtherStuff) \(date.dateFormatted)"
lines.append(l)
}
return lines
}
Und ändern Sie die Ansicht:
var body: some View {
ScrollView {
List {
ForEach(model.summary(), id: \.self) { line in
Text(line)
}
}
}
}
Dies funktioniert jedoch nicht: Die Liste enthält überhaupt keinen Text. Sie wird nie aktualisiert, wenn der Benutzer ein Datum hinzufügt model.selectedDates
.
Was mache ich falsch?
Antworten
Ich konnte diese Antwort auf einen früheren Beitrag zu SO finden, der möglicherweise die Lösung für Ihr Problem darstellt. Wenn Sie sagen, dass die Liste überhaupt keinen Text enthält, haben Sie das debuggt, um dies zu überprüfen, oder wurden einfach keine Daten auf dem Bildschirm angezeigt?
Als ich eine Kopie Ihres Code-Snippets erstellte und damit herumfummelte, schien es, dass die Liste tatsächlich Daten enthielt, die die Liste auf dem Bildschirm anzeigen wollte, aber der Rahmen der Liste wurde von der Bildlaufansicht überschrieben. Durch das Verschachteln aller Elemente in einem GeometryReader und das Festlegen einer Rahmengröße für die Liste erhielt das Programm die Funktionalität, nach der Sie suchen.
Verwenden Sie entweder eine ScrollView oder eine Liste für Ihre Daten. Wenn eine Liste mehrere Werte hat, wird sie automatisch in eine scrollbare Liste umgewandelt. Ich glaube, Sie können ScrollView einfach vollständig entfernen.
Hier ist eine fest bearbeitete Variante (mit einigen Replikationen - Sie müssen sie also wieder an Ihr Projekt anpassen).
Getestet mit 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)
}
}
}
}
}