将加载的json文件中的更改保存到SwiftUI中的核心数据中



我想用json文件加载我的数据。到目前为止还不错。但现在我在挣扎。如果用户对Oil Object进行了一些更改并希望保存这些更改,该怎么办?我的想法是,我将更改后的oils对象保存到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)")
}
}

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

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

这将获取文档目录的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
}
}

最新更新