ser log guide developer desarrollador como apple cocoa core-data nsdictionary nscopying

cocoa - log - ios frameworks



NSManagedObject como clave NSDictionary? (4)

¿Podría crear una clase contenedora que contenga una referencia a la instancia de NSManagedObject que desea usar como clave de diccionario? Luego, podría hacer que esta clase de contenedor implemente NSCopying, junto con un método hash (tal vez simplemente llamando al método de hash de NSManagedObject), y usar este contenedor como clave del diccionario.

En mi aplicación, tengo un NSDictionary cuyas claves deberían ser instancias de una subclase de NSManagedObject .

Sin embargo, el problema es que NSManagedObject no implementa el protocolo NSCopying , lo que significa que no se pueden usar objetos / instancias de Core Data de NSManagedObject como claves de diccionario, aunque el método -[hash] funciona bien para ellos.

¿Debo hacer?


Hay cuatro opciones:

  1. Use un objeto diferente como clave del diccionario en su lugar, y busque desde eso. [object objectID] o +[NSValue valueWithNonretainedObject:] parece ser el más obvio
  2. Use CFDictionaryCreateMutable() para crear un diccionario con claves retenidas , en lugar de copiarlo, y luego llame a CFDictionarySetValue() para almacenar los objetos
  3. En OS X o iOS6 +, [NSMapTable mapTableWithStrongToStrongObjects] le proporciona un equivalente puramente Objective-C a CFMutableDictionary
  4. Implemente NSCopying para su subclase de objeto administrado, de manera que se devuelva a sí mismo (con un recuento de referencias superpuestas si no está usando ARC)

Notas

+valueWithNonretainedObject: es bastante peligroso, ya que se puede dejar con un puntero colgante; probablemente mejor evitar

El almacenamiento de ID de objetos está bien, aparte del hecho de que los nuevos objetos comienzan la vida con un ID temporal . Esa ID luego cambia a una permanente cuando el contexto se guarda en el disco (u -obtainPermanentIDsForObjects:… se llama). Su código de asignación debe ser lo suficientemente inteligente como para manejar esto a menos que pueda garantizar que todos los objetos entrantes ya tengan una identificación permanente.

Implementar NSCopying esta manera se siente un poco complicado, pero debería funcionar bien. Como sucede, este es exactamente el enfoque que adopta NSURLSessionTask , supongo para la facilidad de uso del diccionario.

Antes de OS X 10.8 Mountain Lion, solía ser posible crear un NSMutableDictionary regular y luego llamar a CFDictionarySetValue() para ello. Pero ese ya no es el caso; Los nuevos diccionarios ahora tienen copias de llamadas de copia correctas especificadas en el nivel de CF, en lugar de ser NSMutableDictionary una característica de NSMutableDictionary .


Sugiero usar [[[myManagedObject objectID] URIRepresentation] absoluteString] como su clave.


Tuve un problema similar, en el que necesitaba agrupar varias entidades con datos adicionales para cada una, e inicialmente intenté:

@{entity1:data1, @entity2:data2, @entity3:data3}

esto no funcionó por la razón anterior (NSCopying), así que hice:

@[ @{@"entity":entity1, @"data":data1}, @{@"entity":entity2, @"data":data2}, @{@"entity":entity3, @"data":data3} ]

Pero esta solución solo tiene sentido si no necesita un acceso de estilo de diccionario a estas entidades o está dispuesto a iterar para encontrar lo que necesita. En mi caso esto fue un problema de empaquetado. Tenga en cuenta que si pasa estas entidades alrededor de NSManagedObjectContext debe ser el mismo para usarlas.