我正在尝试学习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)将值添加到数组存储中。
现在我的问题是:如果我通过ContentView()中的3个文本字段添加数据,我的列表会自动更新,而不会出现任何问题
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
}我完全不明白的是,如果我从content视图加载数据,我的列表会自动更新,但如果我使用工作表视图的导航视图,这就不起作用了。
提前感谢你的帮助
发布于 2019-10-25 04:08:49
我对此有一个类似的工作解决方案。
在您的情况下,我将修改您的DataModel,如下所示:
class DataModel: Codable, Identifiable, ObservableObject {
var id: UUID = UUID()
@Published var airportName : String = ""
@Published var metar : String = ""
@Published var taf : String = ""
// ...
}然后在你的DataManager中
class DataManager: ObservableObject {
@Published var storage : [DataModel] = [] // No longer need forobjectWillChange.send()
// ...
}然后在你的View中使用它
struct ContentView: View {
@ObservedObject var dm : DataManager
// ...
var body: some View {
VStack {
// ...
List(dm.storage) { item in
// ...
}
}
}
}问题是,自从WWDC的视频以来,发生了很大的变化。
https://stackoverflow.com/questions/58525674
复制相似问题