2012-01-05 10 views
20

Me gustaría almacenar una referencia débil de puesta a cero a un objeto en un NSDictionary. Esto es para una referencia a un padre NSDictionary, por lo que puedo rastrear una estructura grande sin buscar.Objeto débil en un NSDictionary?

No puedo usar __weak aquí; incluso si mi referencia local es débil, el NSDictionary almacenará una referencia fuerte al objeto al que se hizo referencia débilmente. Y, por supuesto, NSDictionary no puede tener objetos nil.

Estoy en iOS, no en Mac, entonces NSHashTable no está disponible. Y solo quiero que un objeto sea débil; el resto aún debería ser fuerte.

(Voy a publicar mi respuesta, así que tengo algo para marcar como aceptada si no hay mejor respuesta. Pero yo estoy esperando que alguien tiene una mejor respuesta.)

+0

Creé [esto] (https://gist.github.com/firelizzard18/6326536) para que sea un diccionario que almacena objetos de manera efectiva poniendo a cero las referencias débiles. Podría ser modificado (y limpiado) para servir a sus propósitos. –

Respuesta

35

En iOS 6+ puede usar NSMapTable y elegir si desea que los objetos y/o las teclas sean débiles o fuertes.

+2

Claramente la mejor respuesta para hoy y para adelante. Gracias. –

+0

Usted tenía mi voto – Carina

+3

NSMapTable podría no comportarse como se esperaba: http://cocoamine.net/blog/2013/12/13/nsmaptable-and-zeroing-weak-references/ – nehz

14

me he decidido por definir una clase de "contenedor" con un solo miembro, como esto:

@interface Parent : NSObject 
@property (nonatomic, weak) id parent; 
@end 

@implementation Parent 

@synthesize parent = _parent; 

- (id)initWithParent: (id)parent; 
{ 
    if ((self = [super init])) { 
     _parent = parent; 
    } 
    return self; 
} 
@end 

Y su uso:

id parentRef = [[Parent alloc] initWithParent: parent]; 
[newElement setObject: parentRef forKey: ParentKey]; 

creo que esto va a funcionar para mí, pero parece loca que no hay una mejor manera integrada en Foundation.

+0

Suena como la única solución para mí, así es como lo habría hecho también. O un 'NSValue' pero eso no se pondría a cero. – mattjgalloway

+1

Tengo el mismo problema y también pensé en un contenedor, todavía no lo intenté, pero estoy tratando de hacer algo parecido a lo que se hace con el bloque 'id __weak weakObject = strongObject; [optionDict setValue: [NSValue valueWithNonretainedObject: tmpObject] forKey: key]; 'Todavía necesito averiguar si funciona. – Andrea

+1

Comentario anterior, pero agregaré este para nuevos visitantes. Lo que Andrea dice que no funcionará, el diccionario retendrá el objeto de todos modos. – Emanuel

6

Hay una manera incorporada; sólo tiene que utilizar:

[array addObject:[NSValue valueWithNonretainedObject:object]]; 

continuación para acceder al objeto más tarde, su uso:

id object = [[array objectAtIndex:i] nonretainedObjectValue]; 

Si el valor ha sido puesto en libertad, ya que agregó que luego "objeto" será un puntero no válido bajo iOS 4.x , y (supongo) será nil en 5.x con ARC habilitado.

EDITAR: mi suposición era incorrecta, no es débil en virtud de ARC (ver discusión a continuación).

+3

No, es un puntero colgante. Pero gracias por la idea. :) –

+0

No se debe acceder nunca al puntero colgando, ya que su objeto está cerca de la muerte en ese momento. Por lo tanto, el acceso al padre aquí debe ser un error de todos modos, que en este caso no está oculto por niling out. – Eiko

+1

@Eiko, estás equivocado. Es un caso común para el patrón del observador. –