Dlaczego @Published aktualizuje tekst, ale nie aktualizuje listy?

Dec 15 2020

Nie rozumiem, dlaczego Textaktualizacje, ale Listnie.

Mam model z @Publishedtablicą dat. Istnieje również metoda generowania tekstu na podstawie dat.

Oto uproszczona wersja:

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")
    }

}

I pokazuję ten tekst moim zdaniem. Oto uproszczona wersja:

struct DataView: View {

    @ObservedObject var model: DataModel

    var body: some View {
        ScrollView {
            Text(model.summary())
        }
    }

}

Działa: kiedy użytkownik z poziomu interfejsu użytkownika w Widoku doda datę do model.selectedDates, tekst podsumowania jest odpowiednio zaktualizowany.


Teraz chcę zastąpić tekst listą wierszy.

Zmieniam metodę:

    func summary() -> [String] {
        var lines: [String] = []
        for date in selectedDates.sorted().reversed() {
            let l = "\(someOtherStuff) \(date.dateFormatted)"
            lines.append(l)
        }
        return lines
    }

I zmień widok:

    var body: some View {
        ScrollView {
            List {
                ForEach(model.summary(), id: \.self) { line in
                    Text(line)
                }
            }
        }
    }

Ale to nie działa: w ogóle nie ma tekstu na liście, nigdy nie jest aktualizowany, gdy użytkownik dodaje datę do model.selectedDates.

Co ja robię źle?

Odpowiedzi

2 Nate Dec 15 2020 at 08:34

Udało mi się znaleźć tę odpowiedź na poprzedni post w SO, który może być rozwiązaniem twojego problemu. Kiedy mówisz, że na liście nie ma żadnego tekstu, czy debugowałeś, aby to sprawdzić, czy po prostu nie było żadnych danych na ekranie?

Kiedy zrobiłem kopię twojego fragmentu kodu i majstrowałem przy nim, okazało się, że w rzeczywistości na liście były dane, które Lista próbowała wyświetlić na ekranie, ale ramka listy była zastępowana przez widok przewijania. Zagnieżdżenie wszystkiego w GeometryReader i nadanie listy rozmiaru ramki nadało programowi funkcjonalność, której szukasz.

1 nicksarno Dec 15 2020 at 10:22

Użyj ScrollView lub listy dla swoich danych. Jeśli lista ma wiele wartości, automatycznie zmienia się w listę przewijalną. Więc uważam, że możesz po prostu całkowicie usunąć ScrollView.

1 Asperi Dec 15 2020 at 10:53

Oto naprawiony wariant (z kilkoma replikacjami - musisz więc dostosować go z powrotem do swojego projektu).

Przetestowano z 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)
                }
            }
        }
    }
    
}