json - 将 JSON 数据存储到 CoreData
问题描述
我想从 API 下载 JSON 并将对象存储到 CoreData 中。JSON的下载和解码工作但我无法将对象直接存储到CoreData中。
我试图为我的对象创建一个实体,但应用程序没有将对象保存到 CoreData。
我总是收到错误:未解决的错误 nilError,操作无法完成。(Foundation._GenericObjCError 错误 0。)。不知道为什么它不再工作了
我用它来下载和解码 JSON:
class ItemDownloader: ObservableObject {
@Published var items: Items = [Item]()
@Environment(\.managedObjectContext) var managedObjectContext
let itemEndpoint = „https:…………“
init() {
guard let url = URL(string: itemEndpoint) else { return }
URLSession.shared.dataTask(with: url) { (data, response, error) in
do {
guard let data = data else { return }
let items = try JSONDecoder().decode(Items.self, from: data)
print(items)
DispatchQueue.main.async {
self.items = items
}
do {
guard let jsonArray = try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]] else {return}
let coreitems: [CoreItem] = jsonArray.compactMap { [weak self] in
guard
let name = $0["name"] as? String,
let id = $0["id"] as? Int16
else {return nil }
print(name)
print(id)
let coreitem = CoreItem(context: self!.managedObjectContext)
coreitem.name = name
coreitem.id = id
print(coreitem.name)
print(coreitem.id)
return coreitem
}
do{
try self.managedObjectContext.save()
} catch{
print(error)
}
print(coreitems)
print(NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).last!);
}
} catch {
print("Error decoding JSON: ", error)
}
}.resume()
}
}
并将其存储到 CoreData 中:
public class CoreItem: NSManagedObject, Identifiable {
@NSManaged public var name: String
@NSManaged public var id: Int16
}
extension CoreItem {
static func getAllCoreItems() -> NSFetchRequest <CoreItem> {
let request:NSFetchRequest<CoreItem> = CoreItem.fetchRequest() as!
NSFetchRequest<CoreItem>
let sortDescriptor = NSSortDescriptor(key: "id", ascending: true)
request.sortDescriptors = [sortDescriptor]
return request
}
}
如何在 CoreData 中保存对象?
谢谢您的帮助。
解决方案
我建议使CoreItem
符合Decodable
.
首先创建两个扩展,以便能够将NSManagedObjectContext
实例传入JSONDecoder
extension CodingUserInfoKey {
static let context = CodingUserInfoKey(rawValue: "context")!
}
extension JSONDecoder {
convenience init(context: NSManagedObjectContext) {
self.init()
self.userInfo[.context] = context
}
}
实现所需的Decodable
方法CoreItem
public class CoreItem: NSManagedObject, Identifiable, Decodable {
@NSManaged public var name: String
@NSManaged public var id: Int16
private enum CodingKeys: String, CodingKey { case name, id}
public required convenience init(from decoder: Decoder) throws {
guard let context = decoder.userInfo[.context] as? NSManagedObjectContext else { fatalError("Error: NSManagedObjectContext not available") }
let entity = NSEntityDescription.entity(forEntityName: "CoreItem", in: context)!
self.init(entity: entity, insertInto: context)
let values = try decoder.container(keyedBy: CodingKeys.self)
name = try values.decode(String.self, forKey: .name)
id = try values.decode(Int16.self, forKey: .id)
}
}
dataTask
代码可以简化为
URLSession.shared.dataTask(with: url) { (data, response, error) in
do {
guard let data = data else { return }
let decoder = JSONDecoder(context: self.managedObjectContext)
let coreitems = try decoder.decode([CoreItem].self, from: data)
print(coreitems)
try self.managedObjectContext.save()
} catch {
print(error)
}
}.resume()
推荐阅读
- c# - C# - 有什么方法可以使用 _addcarry_u64 内在函数?
- maven - maven 发布:使用 git 时使用 NoClassDefFoundError 进行准备
- javascript - 单击时未打开图像选择窗口?
- python - 在 python 中探索 google protobuf
- javascript - 如何使用 react-router 显示组件
防止或允许更改路线 - node.js - 在 NodeJS 中发出同步请求
- ios - 在读取关注者时获取没有权限错误
- css - 在 div 列表中按类名选择第一个元素(仅限 css)
- python - 组合 2 个 itertools 产品列表以获得更大的组合以查找所有组合
- javascript - 设置二维数组的最大参数