Я пытаюсь изучить SwiftUI, я пытаюсь обновить свой список автоматически, как только я вставлю значение. но я получаю большую проблему! мой список не обновляется, когда я использую лист или навигационное представление для вставки данных, он работает только в том случае, если я загружаю данные из моего contentView.
(и я не понимаю, почему класс DataManager имеет ObservableObject и т. д. он работает отлично, если я загружаю данные с 3 текстовыми полями в представлении содержимого)
здесь, под моим проектом: у меня есть модель данных
import Foundation
import Combine
class DataModel: Codable, Identifiable {
var id: UUID = UUID()
var airportName : String
var metar : String
var taf : String
init(airportName: String, metar: String, taf: String) {
self.airportName = airportName
self.metar = metar
self.taf = taf
}
}
У меня есть DataManager
import SwiftUI
import Combine
class DataManager: ObservableObject {
let objectWillChange = PassthroughSubject<Void, Never>()
var storage : [DataModel] = [] {
willSet {
objectWillChange.send()
}
}
typealias Storage = [DataModel]
var filePath : String = ""
init() { caricaDati() }
func caricaDati() {
// creiamo il percorso al file
filePath = cartellaDocuments() + "test.plist"
// usiamo NSFileManager per sapere se esiste un file a quel percorso
if FileManager.default.fileExists(atPath: filePath) {
// se c'è de-archiviamo il file di testo nell'array
// serve il blocco do try catch
do {
// proviamo a caricare il file dal percorso creato in precedenza
let data = try Data(contentsOf: URL(fileURLWithPath: filePath))
// creiamo il decoder
let decoder = PropertyListDecoder()
// proviamo a decodificare il file nell'array
storage = try decoder.decode(Storage.self, from: data)
} catch {
// se non ce la fa scriviamo in console l'errore
debugPrint(error.localizedDescription)
}
}
}
func salva() {
objectWillChange.send()
let encoder = PropertyListEncoder()
encoder.outputFormat = .xml // impostiamo l'output corretto
// serve il blocco do try catch
do {
// proviamo a codificare l'array
let data = try encoder.encode(storage)
// proviamo a salvare l'array codificato nel file
try data.write(to: URL(fileURLWithPath: filePath))
} catch {
// se non ce la fa scriviamo in console l'errore
debugPrint(error.localizedDescription)
}
}
func newData (nomeApt: String, metar: String, taf: String) {
let newadd = DataModel(airportName: nomeApt, metar: metar, taf: taf)
objectWillChange.send()
storage.append(newadd)
objectWillChange.send()
salva()
}
func cartellaDocuments() -> String {
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
//print(paths[0])
return paths[0]
}
}
Как вы можете видеть, Datamanager - это ObservableObject! и у меня есть простая функция (newData) для добавления значения в хранилище массива.
Теперь моя проблема: если я добавляю данные через 3 текстовых поля в ContentView (), мой список автоматически обновляется без каких-либо проблем.
import SwiftUI
struct ContentView: View {
@ObservedObject var dm : DataManager
@State var isAddPresented : Bool = false
@State var nomeApt : String = ""
@State var metar : String = ""
@State var taf : String = ""
var body: some View {
VStack {
Button(action: {
self.dm.newData(nomeApt: self.nomeApt, metar: self.metar, taf: self.taf)
}) {
Text("Add from below")
}
TextField("name apt", text: $nomeApt)
TextField("name apt", text: $metar)
TextField("name apt", text: $taf)
Button(action: {
self.isAddPresented = true
}) {
Text("open view to add")
}.sheet(isPresented: $isAddPresented) {
Add(dm: DataManager(), dismissFlag: self.$isAddPresented)
}
List(dm.storage) { item in
HStack {
Text(item.airportName)
Text(item.metar)
Text(item.taf)
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(dm: DataManager())
}
}
но если я использую лист для добавления тех же данных, используя ту же функцию, список не обновляется немедленно!
здесь мое второе представление:
import SwiftUI
struct Add: View {
@ObservedObject var dm : DataManager
@State var nomeApt : String = ""
@State var metar : String = ""
@State var taf : String = ""
@Binding var dismissFlag: Bool
var body: some View {
VStack {
Spacer()
TextField("name apt", text: $nomeApt)
TextField("name apt", text: $metar)
TextField("name apt", text: $taf)
Button(action: {
self.dm.newData(nomeApt: self.nomeApt, metar: self.metar, taf: self.taf)
self.dismissFlag = false
}) {
Text("Aggiungi")
}
Spacer()
}
}
}
struct Add_Previews: PreviewProvider {
static var previews: some View {
Add(dm: DataManager(), dismissFlag: bindBool())
}
}
func bindBool() -> Binding<Bool> {
var boolVariable : Bool = true
let boolVariableBinding : Binding<Bool> = Binding(get: { boolVariable },
set: { boolVariable = $0 })
return boolVariableBinding
}
я совершенно не понимаю, почему, если я загружаю данные из представления содержимого, мой список обновляется автоматически, но если я использую навигационный вид представления листа, это не сработает.
заранее спасибо запомощь