Por que @Published atualiza o texto, mas não atualiza a lista?
Não entendo por que as Text
atualizações, mas List
não.
Tenho um modelo com @Published
uma matriz de datas. Também existe um método para gerar texto a partir das datas.
Esta é uma versão simplificada:
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")
}
}
E eu mostro esse texto no meu ponto de vista. Esta é uma versão simplificada:
struct DataView: View {
@ObservedObject var model: DataModel
var body: some View {
ScrollView {
Text(model.summary())
}
}
}
Funciona: quando o usuário, da IU na Visualização, adiciona uma data model.selectedDates
, o texto do resumo é atualizado corretamente.
Agora quero substituir o texto por uma lista de linhas.
Eu mudo o método:
func summary() -> [String] {
var lines: [String] = []
for date in selectedDates.sorted().reversed() {
let l = "\(someOtherStuff) \(date.dateFormatted)"
lines.append(l)
}
return lines
}
E mude a visão:
var body: some View {
ScrollView {
List {
ForEach(model.summary(), id: \.self) { line in
Text(line)
}
}
}
}
Mas isso não funciona: não há nenhum texto na lista, ela nunca é atualizada quando o usuário adiciona uma data a model.selectedDates
.
O que estou fazendo de errado?
Respostas
Consegui encontrar essa resposta em um post anterior no SO que pode ser a solução para o seu problema. Quando você disse que não havia nenhum texto na lista, você depurou para verificar isso ou simplesmente não havia dados sendo mostrados na tela?
Quando fiz uma cópia do seu trecho de código e mexi nele, parecia que realmente havia dados na lista que a Lista estava tentando exibir na tela, mas o quadro da Lista estava sendo substituído pela Visualização de rolagem. Aninhar tudo dentro de um GeometryReader e dar um tamanho de quadro à Lista deu ao programa a funcionalidade que parece que você está procurando.
Use um ScrollView ou uma Lista para seus dados. Se uma lista tiver vários valores, ela se tornará automaticamente uma lista rolável. Então, acredito que você pode simplesmente remover o ScrollView inteiramente.
Aqui está uma variante corrigida (com algumas réplicas - então você precisa adaptá-la de volta ao seu projeto).
Testado com 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)
}
}
}
}
}