NSManagedObject 和 Codable 用于存储在服务器和本地存储中的类
Posted
技术标签:
【中文标题】NSManagedObject 和 Codable 用于存储在服务器和本地存储中的类【英文标题】:NSManagedObject and Codable for class stored in server and local storage 【发布时间】:2018-09-22 17:35:13 【问题描述】:我正在创建一个表示本地存储或来自在线的数据的类。在运行时,我将使用 get 请求从服务器获取这些对象的数组,并将它们与 CoreData 中的现有对象进行比较,以确定用于应用程序和存储的新对象集。
因此,我创建了一个代表我的对象的 CoreData 托管类,它继承了NSManagedObject
。这将允许我处理本地存储,将数组放入存储中并在应用程序完成后放回一个新的。
然后我想使这个类可编码,这样我就可以实现required public init(from decoder: Decoder)
方法,该方法允许我在获取请求中获取这样的对象数组。 JSONDecoder().decode([DataClass].self, from: data!)
.
我尝试了两种方法,但它们都不起作用。
问题:
我在类范围内有一个private enum CodingKeys: String, CodingKey ...
,使用它进行编码效果很好,但无论出于何种原因,都会触发一个错误,指出该类没有实现我无意实现的编码。我不知道为什么这很重要。
我可以将枚举放在初始化程序的范围内,但如果我这样做,就会弹出一个新问题。我必须调用NSManagedObject
的指定初始化程序。这是一个问题,因为该调用需要NSManagedObjectContext
,而我没有。
作为替代方案:
我创建了一个方法func getDataClass(from decoder: Decoder) -> DataClass?
,但这也带来了两个问题。我仍然必须以某种方式初始化 DataClass
对象,但我不知道如何将其带入 JSONDecoder().decode([DataClass].self, from: data!)
行。
【问题讨论】:
【参考方案1】:你必须使DataClass
符合Codable
。
首先创建两个扩展,以便能够传递userInfo
字典中的NSManagedObjectContext
JSONDecoder
。
extension CodingUserInfoKey
static let context = CodingUserInfoKey(rawValue: "context")!
extension JSONDecoder
convenience init(context: NSManagedObjectContext)
self.init()
self.userInfo[.context] = context
以下示例仅使用DataClass
中的一个属性name
。Codable
方法必须在类中,而不是在 CoreDataProperties 扩展中。
class DataClass: NSManagedObject, Codable
private enum CodingKeys: String, CodingKey case name
func encode(to encoder: Encoder) throws
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(name, forKey: .name)
required convenience init(from decoder: Decoder) throws
guard let context = decoder.userInfo[.context] as? NSManagedObjectContext else fatalError("Error: NSManagedObject not specified!")
let entity = NSEntityDescription.entity(forEntityName: "DataClass", in: context)!
self.init(entity: entity, insertInto: context)
let values = try decoder.container(keyedBy: CodingKeys.self)
name = try values.decode(String.self, forKey: .name)
要使用解码器,您必须使用初始化程序
let context = // get the managed object context
let decoder = JSONDecoder(context: context)
【讨论】:
这是一个很好的解决方案!但我有点困惑。当我们抓取实体和上下文时,我们实际上并没有使用它们或更改它们的任何内容,对吗?这只是一种解决方法。 使用此代码,您可以从 JSON 创建核心数据记录并从核心数据记录创建 JSON。如果您不需要后者,请将一致性更改为Decodable
并删除 encode(to encoder
如果没有该方法,我会收到一条错误消息,指出该类不符合 Decodable。它就像是 NSManagedObject 或 Codable 的子类
而且我仍然需要上下文和实体才能使用指定的初始化器
如果DataClass
有一个[String]
或[Int]
类型的属性成员,我们如何编码这些属性?也就是说,我们需要指定case ArrayOfStrings
和/或case ArrayOfInts
。以上是关于NSManagedObject 和 Codable 用于存储在服务器和本地存储中的类的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Core Data 中使用 swift 4 Codable?
如何在 Core Data 中使用 swift 4 Codable?