Swift:在Core Data中插入可编码对象



我正在从API获得响应并解码响应,如下所示:

struct MyStuff: Codable {
let name: String
let quantity: Int
let location: String
}

我有一个实例实体映射MyStuff:

@objc(Stuff)
public class Stuff: NSManagedObject {
}
extension Stuff {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Stuff> {
return NSFetchRequest<Stuff>(entityName: "Stuff")
}
@NSManaged public var name: String?
@NSManaged public var quantity: Int64
@NSManaged public var location: String?
}

我的问题是,当我有类型MyStuff的响应有一种方法来循环通过键和映射值到核心数据?

例如:

let myStuff = MyStuff(name: "table", quantity: 1, location: "kitchen")
let myStuff = MyStuff(name: "table", quantity: 1, location: "kitchen")
for chidren in Mirror(reflecting: myStuff).children {
print(chidren.label)
print(chidren.value)
/*
insert values to core data
*/
}

我真的很感激你的帮助

明智的解决方案是在Stuff中采用Decodable

编写CodingUserInfoKeyJSONDecoder的扩展

extension CodingUserInfoKey {
static let context = CodingUserInfoKey(rawValue: "context")!
}
extension JSONDecoder {
convenience init(context: NSManagedObjectContext) {
self.init()
self.userInfo[.context] = context
}
}

Stuff中采用Decodable并实现init(from:),必须在类中实现,而不是在扩展

中实现。
@objc(Stuff)
public class Stuff: NSManagedObject, Decodable {
private enum CodingKeys: String, CodingKey { case name, quantity, location }

public required convenience init(from decoder: Decoder) throws {
guard let context = decoder.userInfo[.context] as? NSManagedObjectContext else { fatalError("Error: context doesn't exist!") }
let entity = NSEntityDescription.entity(forEntityName: "Stuff", in: context)!
self.init(entity: entity, insertInto: context)
let values = try decoder.container(keyedBy: CodingKeys.self)
name = try values.decodeIfPresent(String.self, forKey: .name)
quantity = try values.decodeIfPresent(Int64.self, forKey: .quantity) ?? 0
location = try values.decodeIfPresent(String.self, forKey: .location)
}
}

要解码JSON,必须使用方便的初始化器初始化解码器

let decoder = JSONDecoder(context: context)

其中context为当前NSManagedObjectContext实例。

现在您可以直接从JSON中创建Stuff实例。

如果不支持每个字段的查询,可以将整个对象存储为JSONString。如果您需要查询某些字段,则将该字段保存在实体对象中。

struct MyStuff: Codable {
let name: String
let quantity: Int
let location: String
}

extension Encodable {
func toString() -> String? {
if let config = try? JSONEncoder().encode(self) {
return String(data: config, encoding: .utf8)
}
return .none
}
}

extension Decodable {
static func map(JSONString: String) -> Self? {
try? JSONDecoder().decode(Self.self, from: JSONString.data(using: .utf8) ?? .init())
}
}


@objc(Stuff)
public class Stuff: NSManagedObject {
}

// Entity with single field (no field base query support)
extension Stuff {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Stuff> {
return NSFetchRequest<Stuff>(entityName: "Stuff")
}
@NSManaged public var myStuffRawJSON: String?

func mapToMyStuff() -> MyStuff? {
MyStuff.map(JSONString: myStuffRawJSON ?? "")
}
}

如何使用:

let myStuff = MyStuff(name: "table", quantity: 1, location: "kitchen")
let entity: Stuff //Create entity
entity.myStuffRawJSON = myStuff.toString()
// save your entity

最新更新