首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ObservedObject列表更新

ObservedObject列表更新
EN

Stack Overflow用户
提问于 2019-10-23 22:54:49
回答 1查看 563关注 0票数 1

我正在尝试学习SwiftUI,一旦我插入了值,我将尝试自动更新我的列表。但我遇到了一个大问题!当我使用工作表或导航视图插入数据时,我的列表不会更新,只有当我从contentView加载数据时,它才起作用。

(我不明白为什么,类DataManager是ObservableObject,而且如果我在内容视图中加载带有3个文本字段的数据,那么它可以很好地工作)

下面是我的项目:我有一个数据模型

代码语言:javascript
复制
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

代码语言:javascript
复制
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个文本字段添加数据,我的列表会自动更新,而不会出现任何问题

代码语言:javascript
复制
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())
    }
}

但是,如果我使用工作表添加相同的数据,使用相同的函数,列表不会立即更新!

这是我的第二个观点:

代码语言:javascript
复制
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视图加载数据,我的列表会自动更新,但如果我使用工作表视图的导航视图,这就不起作用了。

提前感谢你的帮助

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-10-25 04:08:49

我对此有一个类似的工作解决方案。

在您的情况下,我将修改您的DataModel,如下所示:

代码语言:javascript
复制
class DataModel: Codable, Identifiable, ObservableObject {
    var id: UUID = UUID()
    @Published var airportName : String = ""
    @Published var metar : String = ""
    @Published var taf : String = ""

    // ...
}

然后在你的DataManager

代码语言:javascript
复制
class DataManager: ObservableObject {

    @Published var storage : [DataModel] = [] // No longer need forobjectWillChange.send()

    // ...
}

然后在你的View中使用它

代码语言:javascript
复制
struct ContentView: View {
    @ObservedObject var dm : DataManager
    // ...

    var body: some View {

        VStack {
            // ...
            List(dm.storage) { item in
                // ...
            }

        }
    }
}

问题是,自从WWDC的视频以来,发生了很大的变化。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58525674

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档