iphone cocoa-touch delegates nsarray retain

iphone - Matriz no retenida para delegados



nfc iphone 6 (10)

En un proyecto Cocoa Touch, necesito una clase específica para tener no solo un único objeto delegado, sino muchos de ellos.

Parece que debería crear una NSArray para estos delegados; el problema es que NSArray mantendría a todos estos delegados retenidos, lo que no debería (por objeto de la convención no debería retener a sus delegados)

¿Debo escribir mi propia clase de matriz para evitar la retención o hay métodos más simples? ¡Gracias!


¿Qué hay de almacenar en la matriz o diccionario?

__weak typeof(pointer) weakPointer = pointer;


Encontré algunas piezas de código del proyecto Three20 sobre este tema, espero que esto ayude ...

NSMutableArray* TTCreateNonRetainingArray() { CFArrayCallBacks callbacks = kCFTypeArrayCallBacks; callbacks.retain = TTRetainNoOp; callbacks.release = TTReleaseNoOp; return (NSMutableArray*)CFArrayCreateMutable(nil, 0, &callbacks); } NSMutableDictionary* TTCreateNonRetainingDictionary() { CFDictionaryKeyCallBacks keyCallbacks = kCFTypeDictionaryKeyCallBacks; CFDictionaryValueCallBacks callbacks = kCFTypeDictionaryValueCallBacks; callbacks.retain = TTRetainNoOp; callbacks.release = TTReleaseNoOp; return (NSMutableDictionary*)CFDictionaryCreateMutable(nil, 0, &keyCallbacks, &callbacks); }


Encontré este poco de código hace un tiempo (no recuerdo a quién atribuirlo).

Es bastante ingenioso, usar una Categoría para permitir la creación de una matriz mutable que no retiene / libera al respaldarla con un CFArray con devoluciones de llamada adecuadas.

@implementation NSMutableArray (WeakReferences) + (id)mutableArrayUsingWeakReferences { return [self mutableArrayUsingWeakReferencesWithCapacity:0]; } + (id)mutableArrayUsingWeakReferencesWithCapacity:(NSUInteger)capacity { CFArrayCallBacks callbacks = {0, NULL, NULL, CFCopyDescription, CFEqual}; // We create a weak reference array return (id)(CFArrayCreateMutable(0, capacity, &callbacks)); } @end

EDITAR Encontró el artículo original: http://ofcodeandmen.poltras.com



Este de NIMBUS sería más simple:

NSMutableArray* NICreateNonRetainingMutableArray(void) { return (NSMutableArray *)CFArrayCreateMutable(nil, 0, nil); } NSMutableDictionary* NICreateNonRetainingMutableDictionary(void) { return (NSMutableDictionary *)CFDictionaryCreateMutable(nil, 0, nil, nil); } NSMutableSet* NICreateNonRetainingMutableSet(void) { return (NSMutableSet *)CFSetCreateMutable(nil, 0, nil); }


No quieres hacer esto! Cocoa Touch tiene varios conceptos para enviar eventos, debe usar el concepto adecuado para cada caso.

  1. Acción de destino: para los controles de IU, como presionar botones. Un remitente, cero o más receptores.
  2. Delegados: Sólo para un remitente y un destinatario.
  3. Notificación: Para un remitente, y cero o más receptores.
  4. KVO: Más fino que las notificaciones.

Lo que debes hacer es mirar cómo usar la clase NSNotificationCenter . Esta es la forma correcta de enviar una notificación que tenga más de un receptor.


Palabra clave: NSHashTable , búsqueda en documentaciones.


Presento una limitación importante de una de las respuestas anteriores, junto con una explicación y una mejora.

Johnmph sugirió usar [NSValue valueWithNonretainedObject:] .

Tenga en cuenta que cuando hace esto, su referencia actúa no como __weak , sino como __unsafe_unretained mientras está dentro del objeto NSValue. Más específicamente, cuando intentes recuperar tu referencia (usando [myNSValue nonretainedObjectValue]), tu aplicación se bloqueará con una señal EXC_BAD_ACCESS si el objeto se ha desasignado antes de esa hora.

En otras palabras, la referencia débil no se establece automáticamente en cero mientras está dentro del objeto NSValue . Esto me tomó un montón de horas para averiguar. He resuelto este problema creando una clase simple con solo una propiedad de referencia débil.

¡Más bellamente, al usar NSProxy , podemos tratar el objeto envoltorio por completo como si fuera el objeto contenido en sí mismo!

// WeakRef.h @interface WeakRef : NSProxy @property (weak) id ref; - (id)initWithObject:(id)object; @end // WeakRef.m @implementation WeakRef - (id)initWithObject:(id)object { self.ref = object; return self; } - (void)forwardInvocation:(NSInvocation *)invocation { invocation.target = self.ref; [invocation invoke]; } - (NSMethodSignature *)methodSignatureForSelector:(SEL)sel { return [self.ref methodSignatureForSelector:sel]; } @end


Verifique la documentación del método NSValue valueWithNonretainedObject:

Este método es útil para evitar que un objeto se retenga cuando se agrega a un objeto de colección (como una instancia de NSArray o NSDictionary).


Yo sugeriría no luchar contra el marco y usar NSPointerArray con NSPointerFunctionsWeakMemory NSPointerFunctionOption esta manera:

NSPointerArray *weakReferencingArray = [NSPointerArray pointerArrayWithOptions:NSPointerFunctionsWeakMemory]; // NSPointerFunctionsWeakMemory - Uses weak read and write barriers // appropriate for ARC or GC. Using NSPointerFunctionsWeakMemory // object references will turn to NULL on last release.

Me sirvió bien en los escenarios, donde tuve que diseñar una matriz de delegados, que se auto-nula las referencias.