Все ли атрибуты с пользовательским типом в core-data должны быть отношениями? - PullRequest
0 голосов
/ 31 декабря 2018

Это дополнительный вопрос из комментариев в следующем Как отобразить вложенные сложные объекты JSON и сохранить их в основных данных? .

Представьте, что у меня уже есть этот код для моегоapp.

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
    }
}

Теперь я решил добавить постоянство для моего приложения.Я просто хочу иметь таблицу поездок.Я хочу показать пассажирам при поездках, но мне не нужен стол для непосредственного опроса пассажиров.Это просто пользовательский объект / свойство поездки.Каждый раз, когда я получаю доступ к пассажиру, это происходит через поездки.

Так есть ли способ, которым я могу создать новый подкласс NSManagedObject с именем «TripEntity» и сохранить своих пассажиров - БЕЗ 1. создания другого подкласса NSManagedObject для «Пассажира»2. Создание отношений с обратными отношениями между пассажиром и поездкой?Проще говоря, я просто хочу, чтобы это было атрибутом.Концептуально для меня это тоже просто атрибут.Это не совсем отношения ...

Или, если вы используете Core-data, то каждый пользовательский тип должен быть явно подклассом NSManagedObject?В противном случае это не будет сохраняться.Я предполагаю, что это также означает, что объект graph .Что ваш график должен быть полным.Все, что находится за пределами графика, игнорируется ...

Я спрашиваю об этом, потому что объект JSON, который я на самом деле хочу сохранить, гигантский, и я пытаюсь сократить объем работы, которую необходимо выполнить.

Ответы [ 2 ]

0 голосов
/ 31 декабря 2018

Вы можете добавить пассажиров в одну сущность Поездки, но поскольку типы атрибутов ограничены, вы должны использовать тип transformable, который может быть довольно дорогим для архивирования и разархивирования объектов.

Наиболее эффективный способ, еслиИсходные данные JSON предназначены для создания сущностей базовых данных для Passenger и Trip и добавления обратных связей.Затем заставьте все NSManagedObject классы принять Codable и добавить методы init(from decoder и encode(to encoder: к каждому классу.

Например, давайте предположим, что класс Trip имеет отношение ко-многим к Passenger это может выглядеть как

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

, а в классе Passenger есть атрибут trip

@NSManaged public var trip: Trip?

, это обязательный инициализатор Decodable в Trip.Декодер может декодировать как массивы, так и наборы.

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)
}

NSManagedObject классы, принимающие Codable, очень удобны для предварительного заполнениябаза данных из данных JSON или создание резервных копий JSON.

0 голосов
/ 31 декабря 2018

Любое пользовательское свойство должно быть чем-то, что может быть представлено как один из типов свойств Базовых данных.Это включает в себя очевидные вещи, как строки и числовые значения.Он также включает в себя «двоичный», который представляет собой все, что может быть преобразовано в / из NSData (Data в Swift).

Из вашего описания, лучший подход, вероятно, к

  1. Примите NSCoding для вашего Passenger класса.
  2. Сделайте свойство passenger типом Core Data "трансформируемого" типа.(кроме того, это должен быть массив пассажиров? У вас есть один связанный пассажир, но ваш вопрос описывает его так, как если бы их было больше одного).
  3. После выполнения # 2 установите «пользовательский класс»поле для имени пассажира, которое будет именем вашего класса-- Passenger.

Если вы сделаете эти две вещи, Core Data автоматически вызовет методы NSCoding для преобразования между Passenger класс и двоичный двоичный объект, который можно сохранить в Core Data.

...