¿Mejores prácticas? - Matriz / Diccionario como un atributo de entidad de datos central [cerrado]

176

Soy nuevo en Core Data. Me he dado cuenta de que los tipos de colección no están disponibles como tipos de atributo y me gustaría saber cuál es la forma más eficiente de almacenar datos de tipo de matriz / diccionario como un atributo (por ejemplo, los elementos que componen una dirección como calle, ciudad, etc. no requiere una entidad separada y se almacena más convenientemente como un diccionario / matriz que atributos / campos separados). Gracias.

RunLoop
fuente
66
Hacer una entidad con campos de cadena de la dirección es probablemente más fácil de utilizar que un diccionario en el que tiene que recordar sus llaves ...
Daniel

Respuestas:

247

No hay matriz "nativa" o tipo de diccionario en Core Data. Puede almacenar una NSArrayo una NSDictionarycomo un atributo transformable. Esto usará el NSCodingpara serializar la matriz o el diccionario a un NSDataatributo (y deserializarlo adecuadamente al acceder). La ventaja de este enfoque es que es fácil. La desventaja es que no puede consultar la matriz o el diccionario (está almacenado como un BLOB en el almacén de datos) y si las colecciones son grandes, es posible que tenga que mover una gran cantidad de datos hacia / desde el almacén de datos (si es un almacén de datos SQLite) solo para leer o modificar una pequeña parte de la colección.

La alternativa es usar Core Data para muchas relaciones para modelar la semántica de la matriz o colección de diccionarios. Las matrices son más fáciles, así que comencemos con eso. Las relaciones de datos centrales a muchos realmente están modelando un conjunto, por lo que si necesita una funcionalidad similar a una matriz, debe ordenar el conjunto (el uso de una propiedad recuperada es una forma conveniente de hacerlo) o agregar un atributo de índice adicional a la entidad que almacena los elementos de la matriz y administra los índices usted mismo. Si está almacenando una matriz homogénea (todas las entradas son del mismo tipo), es fácil modelar la descripción de la entidad para las entidades de la matriz. De lo contrario, tendrá que decidir si usar un atributo transformable para almacenar los datos del artículo o crear una familia de entidades del artículo.

El modelado de un diccionario probablemente requerirá una relación de muchos a un conjunto de entidades que almacena una clave y un valor. Tanto la clave como el valor son análogos a la entidad del elemento para la matriz, descrita anteriormente. Por lo tanto, podrían ser tipos nativos (si los conoce con anticipación), un atributo transformable o una relación con una instancia de una familia de entidades específicas de tipo.

Si todo esto suena un poco desalentador, lo es. El horneado de datos arbitrarios en un marco dependiente del esquema como Core Data es difícil.

Para los datos estructurados, como las direcciones, casi siempre es más fácil pasar el tiempo modelando las entidades explícitamente (por ejemplo, un atributo para cada parte de la dirección). Además de evitar todo el código adicional para modelar un diccionario, esto hace que su interfaz de usuario sea más fácil (los enlaces "simplemente funcionarán") y su lógica de validación, etc., mucho más clara ya que Core Data puede manejar gran parte de ella.

Actualizar

A partir de OS X 10.7, Core Data incluye un tipo de conjunto ordenado que se puede usar en lugar de una matriz. Si puede apuntar a 10.7 o posterior, esta es la mejor solución para colecciones ordenadas (tipo matriz).

Barry Wark
fuente
Secundado: confirmó lo que ya pensaba pero no sabía acerca de los atributos transformables.
jkp
3
@pixelfreak El uso de transformable depende de cómo necesite usar los elementos de la colección. Si necesita consultar en contra de ellos, o si desea poder cargar perezosamente algunos o todos ellos, un atributo transformable no funcionará. Si no necesita una carga lenta, no necesita consultar y siempre necesita todos los elementos o ninguno, un atributo transformable puede funcionar para usted (y ciertamente es fácil de implementar).
Barry Wark
3
Lo que dice Barry se describe con más detalle en la Guía de programación de datos básicos, capítulo Atributos persistentes no estándar .
Palimondo
2
Una nota de precaución sobre los conjuntos ordenados: no los use para relaciones de muchos con más de un par de miles de objetos en el lado múltiple. Si lo hace, guardar puede comenzar a tomar tanto tiempo que bloquea el hilo.
Kirk van Gorkom
2
No entiendo sobre el "nuevo conjunto ordenado". ¿Es un atributo? Porque no puedo verlo en el menú de tipo de atributo.
Trama el
11

Tuve un problema similar. En mi caso, quería mapear una serie de cadenas. Seguí el consejo de Barry y finalmente lo puse a funcionar. Así es como se ve parte del código (que con suerte aclarará las cosas para cualquier persona que se encuentre con esto) ...

Mi entidad se parece a esto:

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

El código de Mi código de modelo de objeto de gestión (datos principales) se parece a esto:

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];

Entonces, los elementos clave aquí son:

  • Estoy usando un NSSet para el tipo de propiedad
  • Estoy usando NSTransformableAttributeType como el tipo de atributo en el Modelo de objeto gestionado de datos básicos.
caleb
fuente
Entonces, ¿habría puesto este código dentro de AppointmentSearchResponse.m dentro de un método init?
Chicowitz