在 SwiftUI 中将加载的 json 文件中的更改保存到 Core Data

Posted

技术标签:

【中文标题】在 SwiftUI 中将加载的 json 文件中的更改保存到 Core Data【英文标题】:Saving changes from a loaded json File to Core Data in SwiftUI 【发布时间】:2021-01-01 20:18:33 【问题描述】:

我想用 json 文件加载我的数据。到现在为止还挺好。但现在我很挣扎。如果用户对油对象进行了一些更改并想要保存它们怎么办?我的想法是,我将更改后的油对象保存到 CoreData。但这有什么可能?因为每次用户启动应用程序时,都会加载未修改的 json 文件,并且用户不会看到他更改的对象。我该如何处理?还是我的想法不对?

struct Oil: Codable, Hashable, Identifiable 
    var id: Int
    
    let image: String
    let color: String
    
    let title: String
    let subtitle: String
    let description: String
    
    var localizedTitle: LocalizedStringKey 
        return LocalizedStringKey(title)
    
    var localizedDescription: LocalizedStringKey 
        return LocalizedStringKey(description)
    
    
    var isFavorite: Bool
    
    static let exampleOil = Oil(id: 10001, image: "",color: "lavenderColor" ,title: "lavender", subtitle: "Lavandula angustifolia", description: "", isFavorite: false)
    


final class Oils: ObservableObject 
    
    var oils: [Oil] = load("oilDatabase.json")



func load<T: Decodable>(_ filename: String) -> T 
    let data: Data

    guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
    else 
        fatalError("Couldn't find \(filename) in main bundle.")
    

    do 
        data = try Data(contentsOf: file)
     catch 
        fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
    

    do 
        let decoder = JSONDecoder()
        return try decoder.decode(T.self, from: data)
     catch 
        fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
    

【问题讨论】:

【参考方案1】:

你真的需要核心数据吗?如果您只是存储一个 json 文件,您可以节省很多复杂性,只需将文件的更新版本写入文档目录。

您所要做的就是检查文件是否存在于文档目录中,如果它确实从那里加载它,否则从您的包中加载它。

这将获取文档目录的 URL

func getDocumentsDirectory() -> URL 
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    return paths[0]

然后我们只需要更新您的load 以在加载之前检查文件是否存在于文档目录中。

func load<T: Decodable>(_ filename: String) -> T 
    let data: Data

    // Check that the fileExists in the documents directory
    let filemanager = FileManager.default
    let localPath = getDocumentsDirectory().appendingPathComponent(filename)

    if filemanager.fileExists(atPath: localPath.path) 
        
        do 
            data = try Data(contentsOf: localPath)
         catch 
           fatalError("Couldn't load \(filename) from documents directory:\n\(error)")
        

     else 
        // If the file doesn't exist in the documents directory load it from the bundle
        guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
        else 
            fatalError("Couldn't find \(filename) in main bundle.")
        

        do 
            data = try Data(contentsOf: file)
         catch 
            fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
        
    


    do 
        let decoder = JSONDecoder()
        return try decoder.decode(T.self, from: data)
     catch 
        fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
    

您还需要保存对 json 所做的任何更改。您可以使用以下函数来做到这一点。

func save<T: Encodable>(_ filename: String, item: T) 

    let encoder = JSONEncoder()
    do 
        let url = getDocumentsDirectory().appendingPathComponent(filename)
        let encoded = try encoder.encode(item)
        let jsonString = String(data: encoded, encoding: .utf8)
        try jsonString?.write(to: url, atomically: true, encoding: .utf8)
     catch 
        // handle your error
    


【讨论】:

谢谢,这很好地解决了我的问题。我现在就试试看。

以上是关于在 SwiftUI 中将加载的 json 文件中的更改保存到 Core Data的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI 从 URL 加载单个对象 JSON

在 SwiftUI 中将 ObservableObject 链接到 DatePicker

SwiftUI:尝试加载本地 JSON 数据时,Canvas 出现预览错误

Swiftui 为 Json 数据项创建加载更多按钮

使用 SwiftUI 2.0 和 Core Data 预填充数据

Swiftui:从 JSON 中获取动态颜色渐变?