Лучшая практика? - Массив/словарь в качестве основного атрибута объекта данных

Я новичок в Core Data. Я заметил, что типы коллекций недоступны в качестве типов атрибутов, и хотел бы знать, какой наиболее эффективный способ хранения данных типа массива/словаря в качестве атрибута (например, элементы, составляющие адрес, такие как улица, город и т. д.). не требует отдельного объекта и удобнее хранится в виде словаря/массива, чем отдельные атрибуты/поля). Спасибо.


person RunLoop    schedule 13.10.2009    source источник
comment
Создание объекта со строковыми полями для адреса, вероятно, проще в использовании, чем словарь, где вы должны помнить свои ключи...   -  person Daniel    schedule 14.10.2009


Ответы (2)


В Core Data нет «родного» массива или типа словаря. Вы можете сохранить NSArray или NSDictionary в качестве трансформируемого атрибута. Это будет использовать NSCoding для сериализации массива или словаря в атрибут NSData (и соответствующим образом десериализовать его при доступе). Преимущество этого подхода в том, что он прост. Недостатком является то, что вы не можете выполнять запросы к массиву или словарю (он хранится в виде BLOB в хранилище данных), и если коллекции большие, вам, возможно, придется перемещать много данных в/из хранилища данных (если оно хранилище данных SQLite) просто для чтения или изменения небольшой части коллекции.

Альтернативой является использование отношений Core Data to-many для моделирования семантики массива или коллекции словарей. Массивы проще, так что давайте начнем с них. Отношения Core Data-to-many на самом деле моделируют набор, поэтому, если вам нужна функциональность, подобная массиву, вы должны либо отсортировать набор (удобным способом сделать это, используя выбранное свойство), либо добавить дополнительный атрибут индекса к объекту. который хранит элементы массива и самостоятельно управляет индексами. Если вы храните однородный массив (все записи одного типа), легко смоделировать описание сущности для сущностей массива. Если нет, вам придется решить, использовать ли преобразуемый атрибут для хранения данных элемента или создать семейство сущностей элемента.

Моделирование словаря, скорее всего, потребует отношения «ко многим» к набору сущностей, в котором хранятся ключ и значение. И ключ, и значение аналогичны сущности элемента для массива, описанной выше. Таким образом, они могут быть либо собственными типами (если вы знаете их заранее), трансформируемым атрибутом или отношением к экземпляру из семейства сущностей, специфичных для типа.

Если все это звучит немного пугающе, так оно и есть. Втиснуть произвольные данные в зависимую от схемы структуру, такую ​​как Core Data, непросто.

Для структурированных данных, таких как адреса, почти всегда проще потратить время на явное моделирование объектов (например, атрибут для каждой части адреса). Помимо того, что вы избегаете всего лишнего кода для моделирования словаря, это упрощает ваш пользовательский интерфейс (привязки будут «просто работать»), а вашу логику проверки и т. Д. Гораздо понятнее, поскольку большая часть этого может быть обработана Core Data.

Обновить

Начиная с OS X 10.7, Core Data включает тип упорядоченного набора, который можно использовать вместо массива. Если вы можете ориентироваться на 10.7 или более позднюю версию, это лучшее решение для упорядоченных (массивных) коллекций.

person Barry Wark    schedule 13.10.2009
comment
Прикомандирован - подтвердил то, что я уже думал, но не знал о трансформируемых атрибутах. - person jkp; 02.06.2010
comment
@Barry Так что мне любопытно, когда будет подходящее время для использования трансформируемого? Скажем, если у моего объекта есть массив строк, массив содержит не более 100 элементов, а строка представляет собой среднее английское слово, можно ли использовать трансформируемый? - person pixelfreak; 21.07.2011
comment
@pixelfreak Использование трансформируемого зависит от того, как вам нужно использовать элементы в коллекции. Если вам нужно выполнить запрос к ним или вы хотите иметь возможность лениво загружать некоторые или все из них, преобразуемый атрибут не будет работать. Если вам не нужна ленивая загрузка, не нужно запрашивать и всегда нужны все элементы или ничего, трансформируемый атрибут может вам подойти (и, безусловно, его легко реализовать). - person Barry Wark; 18.08.2011
comment
То, что говорит Барри, более подробно описано в Руководстве по программированию основных данных, глава Нестандартные постоянные атрибуты. - person Palimondo; 01.09.2011
comment
Очень хороший ответ, спасибо. Мне нужен был небольшой, фактически постоянный массив строк в существующей модели, и у меня не было никакого желания начинать добавлять новые отношения и модели. Я просто использовал тип Transformable в модели и объявил свойство NSArray в моем подклассе NSManagedObjectModel, как подробно описано в ссылке @Palimodo выше. И он также работал без проблем, загружая массив из plist, используя setValuesForKeysWithDictionary:. - person Echelon; 13.05.2012
comment
Предупреждение об упорядоченных наборах: не используйте их для отношений ко-многим с более чем парой тысяч объектов на стороне многих. В противном случае сохранение может занять так много времени, что поток будет заблокирован. - person Kirk van Gorkom; 30.06.2012
comment
Я не понимаю насчёт нового заказанного набора. Это атрибут? Потому что я не вижу его в меню типа атрибута. - person Plot; 22.01.2014
comment
Неважно, я выбрал метод отношений :) спасибо! - person Plot; 22.01.2014

У меня была аналогичная проблема. В моем случае я хотел отобразить массив строк. Я последовал совету Барри и, наконец, заработал. Вот как выглядит часть кода (который, надеюсь, прояснит ситуацию для всех, кто столкнется с этим)...

Моя сущность выглядит примерно так:

@interface AppointmentSearchResponse : NSManagedObject
@property (nonatomic, retain) NSSet *messages;
@end

Мой код управления объектной моделью (базовые данные) выглядит примерно так:

NSEntityDescription *entityDescription = [[NSEntityDescription alloc] init];
[entityDescription setName:@"AppointmentSearchResponse"];
[entityDescription setManagedObjectClassName:@"AppointmentSearchResponse"];

NSMutableArray *appointmentSearchResponseProperties = [NSMutableArray array];
NSAttributeDescription *messageType = [[NSAttributeDescription alloc] init];    
[messageType setName:@"messages"];
[messageType setAttributeType:NSTransformableAttributeType];
[appointmentSearchResponseProperties addObject:messageType];

[entityDescription setProperties:appointmentSearchResponseProperties];

Итак, ключевые пункты здесь:

  • Я использую NSSet для типа свойства
  • Я использую NSTransformableAttributeType в качестве типа атрибута в объектной модели Core Data Managed Object Model.
person caleb    schedule 23.01.2012
comment
Итак, поместили бы вы этот код внутрь AppointmentSearchResponse.m в методе инициализации? - person Chicowitz; 06.09.2015