代码之家  ›  专栏  ›  技术社区  ›  mfaani

核心数据中具有自定义类型的所有属性都必须是关系吗?

  •  0
  • mfaani  · 技术社区  · 6 年前

    这是以下评论中的后续问题 How to map nested complex JSON objects and save them to core data? .

    假设我的应用程序已经有了这个代码。

    class Passenger{
        var name: String
        var number: String
        var image : UIImage
        // init method
    }
    class Trip {
        let tripNumber : Int
        let passenger : Passenger
    
        init(tripNumber: Int, passenger: Passenger) {
            self.tripNumber = tripNumber
            self.passenger = passenger
        }
    }
    

    现在我决定为我的应用程序添加持久性。我只是 希望 有一张旅行桌。我想给乘客看行程,但不需要表格直接查询乘客。它只是一个定制的旅行对象/财产。每次我进入乘客,都是通过旅行。

    因此,是否有一种方法可以创建一个名为“tripEntity”的nsManagedObject的新子类,并在没有1的情况下存储我的乘客。为“passenger”2创建另一个nsmanagedObject子类。创建一个与乘客和旅行之间的反向关系的关系?简单地说,我只希望它是一个属性。从概念上讲,它也是一个属性。这不是真正的关系…

    或者,一旦使用了核心数据,那么每个自定义类型都需要显式地成为nsmanagedObject的子类?否则它就不会持久。我猜这也是什么东西 图表 手段。你的图表需要完整。图形之外的任何内容都将被忽略…

    我之所以这么问是因为我实际上想要存储的JSON对象是巨大的,我正试图减少需要完成的工作。

    2 回复  |  直到 6 年前
        1
  •  1
  •   Tom Harrington    6 年前

    任何自定义属性都必须是可以表示为核心数据属性类型之一的属性。其中包括字符串和数值等明显的内容。它还包括“二进制”,这是任何可以转换为/来自 NSData ( Data 在斯威夫特)

    根据您的描述,最好的方法可能是

    1. 采用 NSCoding 为了你 Passenger 班级。
    2. 使 passenger 属性核心数据“可转换”类型。(顺便说一下,这应该是一组乘客吗?你有一个相关的乘客,但你的问题描述的好像不止一个)。
    3. 完成2后,将乘客财产的“自定义类”字段设置为您的类的名称。-- 乘客 .

    如果您执行这两项操作,核心数据将自动调用 非编码 在您的 乘客 类和可以保存在核心数据中的二进制blob。

        2
  •  2
  •   vadian    6 年前

    您可以将乘客添加到一个旅行实体,但是由于属性类型受到限制,您必须使用 transformable 对对象进行归档和取消归档可能会非常昂贵。

    如果源数据是JSON,最有效的方法是为 Passenger Trip 并添加反向关系。然后使一切 NSManagedObject 课堂采用 Codable 并添加 init(from decoder encode(to encoder: 每个类的方法。

    例如,假设 旅行 类与 乘客 看起来像

    @NSManaged public var tripNumber: Int32
    @NSManaged public var passengers: Set<Passenger>
    

    而在 乘客 类有一个属性 trip

    @NSManaged public var trip: Trip?
    

    这是必需的 Decodable 初始化器 旅行 . 解码器可以对数组和集合进行解码。

    private enum CodingKeys: String, CodingKey { case tripNumber, passengers }
    
    public required convenience init(from decoder: Decoder) throws {
        guard let context = decoder.userInfo[.context] as? NSManagedObjectContext else { fatalError("Context Error") }
        let entity = NSEntityDescription.entity(forEntityName: "Trip", in: context)!
        self.init(entity: entity, insertInto: context)
        let values = try decoder.container(keyedBy: CodingKeys.self)
        tripNumber = try values.decode(Int32.self, forKey: .tripNumber)
        passengers = try values.decode(Set<Passenger>.self, forKey: .passengers)
        passengers.forEach{ $0.trip = self }
    }
    

    反向关系是通过 forEach 线。
    您必须添加扩展名 JSONDecoder 能通过电流 NSManagedObjectContext userInfo 对象。

    相应的编码器是“非常简单的”

    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(tripNumber, forKey: .tripNumber)
        try container.encode(passengers, forKey: .passengers)
    }
    

    被管理对象 课程采用 可编的 对于从JSON数据预填充数据库或进行JSON备份非常舒适。