cocoa data-structures nsdictionary nsmutabledictionary

cocoa - NSDictionary de cacao: ¿por qué se copian las claves?



data-structures nsmutabledictionary (3)

Todos los objetos utilizados como claves en los diccionarios NS (mutables) deben ser compatibles con el protocolo NSCopying, y esos objetos se copian cuando se utilizan en el diccionario.

Con frecuencia, quiero usar objetos de mayor peso como claves, simplemente para asignar un objeto a otro. Lo que realmente quiero decir cuando hago eso es efectivamente:

[dictionary setObject:someObject forKey:[NSValue valueWithPointer:keyObject]];

("Cuando vuelva y te entregue esta misma instancia de objeto clave de nuevo, sácame ese mismo valor").

... que es exactamente lo que termino haciendo para sortear este diseño a veces. (Sí, conozco NSMapTable en el escritorio de Cocoa; pero, por ejemplo, el iPhone no lo admite).

Pero lo que realmente no entiendo es por qué copiar la clave es necesario o deseable en primer lugar. ¿Qué compra la implementación o el que llama?


Desde iOS 6, si desea usar punteros como claves, puede usar el objeto NSMapTable , consulte http://nshipster.com/nshashtable-and-nsmaptable/

Puede especificar si las claves y / o los valores se mantienen de forma rígida o débil:

NSMapTable *mapTable = [NSMapTable mapTableWithKeyOptions:NSMapTableStrongMemory valueOptions:NSMapTableWeakMemory];

Otra opción que podría ser apropiada a veces es usar NSCache , que mantiene las teclas con fuerza y ​​en realidad es seguro para subprocesos.


La copia garantiza que los valores utilizados como claves no cambien "de forma directa" mientras se utilizan como claves. Considere el ejemplo de una cadena mutable:

NSMutableString* key = ... NSMutableDictionary* dict = [[NSMutableDictionary alloc] init]; [dict setObject: ... forKey: key];

Supongamos que el diccionario no copió la clave, sino que simplemente la retain . Si ahora, en algún momento posterior, se modifica la cadena original, entonces es muy probable que no vuelva a encontrar su valor almacenado en el diccionario, incluso si usa el mismo objeto clave (es decir, la única key apunta a). en el ejemplo de arriba).

Para protegerse contra tal error, el diccionario copia todas las claves.

Tenga en cuenta, por cierto, que es lo suficientemente simple como para definir -copyWithZone: como solo hacer return [self retain] . Esto está permitido y es un buen código si su objeto es inmutable, y el contrato NSCopying está diseñado específicamente de modo que el objeto devuelto tiene que ser (sorta, algo) inmutable:

Implemente NSCopying conservando el original en lugar de crear una nueva copia cuando la clase y su contenido sean inmutables.

( De referencia de NSCopying )

y

La copia devuelta es inmutable si la consideración "inmutable contra mutable" se aplica al objeto receptor; de lo contrario, la naturaleza exacta de la copia está determinada por la clase.

(De -copyWithZone: Referencia )

Incluso si sus objetos no son inmutables, podría salirse con la suya si solo utiliza implementaciones de igualdad / hash basadas en la identidad, es decir, implementaciones que no se vean afectadas de ninguna manera por el estado interno del objeto.


Si desea almacenar los punteros como claves, deberá envolverlos en un objeto NSValue con +valueWithPointer: