Melhor prática? - Matriz / dicionário como um atributo principal da entidade de dados [fechado]

176

Eu sou novo no Core Data. Percebi que os tipos de coleção não estão disponíveis como tipos de atributo e gostaria de saber qual é a maneira mais eficiente de armazenar dados de tipo de matriz / dicionário como um atributo (por exemplo, os elementos que compõem um endereço como rua, cidade etc. não requer uma entidade separada e é mais convenientemente armazenada como um dicionário / matriz do que atributos / campos separados). Obrigado.

RunLoop
fonte
6
Fazendo uma entidade com campos de cadeia para o endereço é provavelmente mais fácil de usar do que um dicionário onde você tem que lembrar suas chaves ...
Daniel

Respostas:

247

Não há matriz "nativa" ou tipo de dicionário no Core Data. Você pode armazenar um NSArrayou um NSDictionaryatributo como transformável. Isso usará o NSCodingpara serializar a matriz ou dicionário para um NSDataatributo (e desserializar adequadamente após o acesso). A vantagem dessa abordagem é que é fácil. A desvantagem é que você não pode consultar a matriz ou o dicionário (ele é armazenado como um BLOB no repositório de dados) e, se as coleções forem grandes, poderá ser necessário mover muitos dados para / do repositório de dados (se for um armazenamento de dados SQLite) apenas para ler ou modificar uma pequena parte da coleção.

A alternativa é usar os relacionamentos Core Data para muitos para modelar a semântica da matriz ou coleção de dicionário. As matrizes são mais fáceis, então vamos começar com isso. Os relacionamentos Core Data para muitos estão realmente modelando um conjunto; portanto, se você precisar de uma funcionalidade semelhante a uma matriz, terá que classificar o conjunto (usar uma propriedade buscada é uma maneira conveniente de fazer isso) ou adicionar um atributo de índice extra à entidade que armazena os itens da matriz e gerencia você mesmo os índices. Se você estiver armazenando uma matriz homogênea (todas as entradas são do mesmo tipo), é fácil modelar a descrição da entidade para as entidades da matriz. Caso contrário, você terá que decidir se deseja usar um atributo transformável para armazenar os dados do item ou criar uma família de entidades do item.

A modelagem de um dicionário provavelmente exigirá uma relação de muitos com um conjunto de entidades que armazena uma chave e um valor. Tanto a chave quanto o valor são análogos à entidade do item para a matriz, descrita acima. Portanto, eles podem ser tipos nativos (se você os conhecer com antecedência), um atributo transformável ou um relacionamento com uma instância de uma família de entidades específicas do tipo.

Se tudo isso parece um pouco assustador, é. Colocar dados arbitrários em uma estrutura dependente de esquema como o Core Data é difícil.

Para dados estruturados, como endereços, é quase sempre mais fácil gastar o tempo modelando explicitamente as entidades (por exemplo, um atributo para cada parte do endereço). Além de evitar todo o código extra para modelar um dicionário, isso facilita a interface do usuário (as ligações "funcionarão") e a lógica de validação etc. muito mais clara, pois grande parte dele pode ser manipulada pelo Core Data.

Atualizar

No OS X 10.7, o Core Data inclui um tipo de conjunto ordenado que pode ser usado no lugar de uma matriz. Se você pode segmentar 10.7 ou posterior, esta é a melhor solução para coleções ordenadas (do tipo matriz).

Barry Wark
fonte
Destacado - confirmou o que eu já pensava, mas não sabia sobre atributos transformáveis.
Jkp
3
@pixelfreak O uso do transformble depende de como você precisa usar os itens da coleção. Se você precisar consultá-los ou desejar carregar preguiçosamente alguns ou todos eles, um atributo transformável não funcionará. Se você não precisa carregar preguiçosamente, não precisa consultar e sempre precisa de todos os itens ou nenhum, um atributo transformável pode funcionar para você (e certamente é fácil de implementar).
Barry Wark
3
O que Barry diz está descrito em mais detalhes no Guia de programação de dados principais, no capítulo Atributos persistentes não padrão .
Palimondo 01/09/11
2
Uma nota de cautela sobre conjuntos ordenados: não os use para relacionamentos com muitos mais de alguns milhares de objetos do lado oposto. Se o fizer, o salvamento pode começar a demorar tanto que bloqueia o encadeamento.
Kirk van Gorkom
2
Eu não entendo sobre o "novo conjunto ordenado". É um atributo? Porque não consigo vê-lo no menu do tipo de atributo.
Traçar
11

Eu tive uma questão semelhante. No meu caso, eu queria mapear uma matriz de strings. Eu segui o conselho de Barry e finalmente o fiz funcionar. Aqui está a aparência de alguns códigos (que esperamos esclarecer as coisas para qualquer pessoa que se depare com isso) ...

Minha entidade é mais ou menos assim:

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

Meu código Manage Code Model Model (Core Data) é mais ou menos assim:

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

Portanto, os itens principais aqui são:

  • Estou usando um NSSet para o tipo de propriedade
  • Estou usando NSTransformableAttributeType como o tipo de atributo no Modelo de Objeto Gerenciado de Dados Principais.
caleb
fonte
Então, você colocaria esse código dentro de AppointmentSearchResponse.m dentro de um método init?
Chicowitz 5/09/2015