【问题标题】:SwiftUI local JSON save string valueSwiftUI 本地 JSON 保存字符串值
【发布时间】:2021-09-10 03:09:52
【问题描述】:

我创建了一个本地 json。我更改了 json 中 name 键的值,当我关闭并打开应用程序时,它再次显示“测试”。如何保存对 Json 文件所做的更改?

为什么我不能保存字符串值?我和你分享了所有的代码。如果你愿意,我可以分享这个项目。

本地 JSON 文件

{
  "person": {
  "name": "Test"
  }
}

型号

struct PersonContainer: Codable {
    var person: Person?
}

struct Person: Codable {
    var name: String?
}

JSON 提供程序

class JSONProvider: ObservableObject {
    
    @Published var personContainer: PersonContainer = PersonContainer()
    var fm = FileManager.default
    var fresult: Bool = false
    @Published var subUrl: URL? = URL(string: "")
    var mainUrl: URL? = Bundle.main.url(forResource: "test", withExtension: "json")
    
    func getData() {
        do {
            let documentDirectory = try fm.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
            subUrl = documentDirectory.appendingPathComponent("test.json")
            loadFile(mainPath: mainUrl!, subPath: subUrl!)
        } catch {
            print(error)
        }
    }
    
    func loadFile(mainPath: URL, subPath: URL){
        if fm.fileExists(atPath: subPath.path){
            decodeData(pathName: subPath)
            
            if ((personContainer.person) != nil) {
                decodeData(pathName: mainPath)
            }
            
        }else{
            decodeData(pathName: mainPath)
        }
    }
    
    func decodeData(pathName: URL){
        do{
            let jsonData = try Data(contentsOf: pathName)
            let decoder = JSONDecoder()
            let personContainer = try decoder.decode(PersonContainer.self, from: jsonData)
            self.personContainer = personContainer
            
        } catch {}
    }
    
    func writeToFile(location: URL) {
        do{
            let encoder = JSONEncoder()
            encoder.outputFormatting = .prettyPrinted
            let JsonData = try encoder.encode(personContainer)
            try JsonData.write(to: location)
        } catch {
            
        }
    }
}

内容视图

struct ContentView: View {
    @State var text: String = ""
    @ObservedObject var jsonProvider: JSONProvider = JSONProvider()
    var body: some View {
        VStack {
            
            TextField("Placeholder", text: $text)
                .padding()
                .background(Color(UIColor.secondarySystemBackground))
                .cornerRadius(15)
                .padding(.horizontal)
                

            Text("Hello, world! \(jsonProvider.personContainer.person?.name ?? "")")
                .padding()
            
            Button(action: {
                jsonProvider.personContainer.person?.name = text
                jsonProvider.writeToFile(location: jsonProvider.subUrl!)
            }) {
                Text("Button")
            }
        }
        .onAppear {
            jsonProvider.getData()
        }
    }
}

【问题讨论】:

    标签: json swiftui file-manager


    【解决方案1】:

    看起来您走在了正确的轨道上,但缺少一些东西。

    由于原始主包的test.json 只有在文档目录中的文件不存在时才应该加载,因此可以简化很多逻辑。例如,您可以删除@PublishedsubUrl,因为它永远不会被更改,也不会被View 观察到。

    确保在按下按钮时调用writeToFile

    此外,在catch 块内执行某事(例如打印error)总是一个好主意,以防出现问题。

    class JSONProvider: ObservableObject {
        
        @Published var personContainer: PersonContainer = PersonContainer()
        private var fm = FileManager.default
        private let mainUrl: URL = Bundle.main.url(forResource: "test", withExtension: "json")!
        
        func getData() {
            if fm.fileExists(atPath: documentDirectoryJSONURL().path) {
                decodeData(fromURL: documentDirectoryJSONURL())
            } else {
                decodeData(fromURL: mainUrl)
            }
        }
        
        func documentDirectoryJSONURL() -> URL {
            do {
                let documentDirectory = try fm.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
                return documentDirectory.appendingPathComponent("test.json")
            } catch {
                fatalError("Couldn't create URL")
            }
        }
        
        func decodeData(fromURL url: URL){
            do{
                let jsonData = try Data(contentsOf: url)
                let decoder = JSONDecoder()
                let personContainer = try decoder.decode(PersonContainer.self, from: jsonData)
                self.personContainer = personContainer
            } catch {
                print(error)
                assertionFailure("Error decoding JSON")
            }
        }
        
        func writeToFile() {
            do{
                let encoder = JSONEncoder()
                encoder.outputFormatting = .prettyPrinted
                let jsonData = try encoder.encode(personContainer)
                try jsonData.write(to: documentDirectoryJSONURL())
            } catch {
                print(error)
            }
        }
    }
    
    struct ContentView: View {
        @State var text: String = ""
        @ObservedObject var jsonProvider: JSONProvider = JSONProvider()
        var body: some View {
            VStack {
                
                TextField("Placeholder", text: $text)
                    .padding()
                    .background(Color(UIColor.secondarySystemBackground))
                    .cornerRadius(15)
                    .padding(.horizontal)
                    
    
                Text("Hello, world! \(jsonProvider.personContainer.person?.name ?? "")")
                    .padding()
                
                Button(action: {
                    jsonProvider.personContainer.person?.name = text
                    jsonProvider.writeToFile()
                }) {
                    Text("Write")
                }
            }
            .onAppear {
                jsonProvider.getData()
            }
        }
    }
    

    【讨论】:

    • 非常感谢先生。你拯救了我的一天。 :)
    • 太棒了——如果您觉得有帮助,请随时点赞
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-24
    • 1970-01-01
    • 2016-04-03
    • 1970-01-01
    • 2020-10-26
    • 2015-11-15
    • 1970-01-01
    相关资源
    最近更新 更多