ios - recuperar - swift tutorial español
¿Cómo recibir una notificación cuando una referencia débil de reducción a cero se convierte en nula en Objective-C bajo ARC? (6)
El siguiente es un ejemplo que utilicé para implementar multidifusión de delegados. Podría ser útil ilustrar cómo monitorear el ''dealloc'' de los objetos de referencia débiles (los delegados).
Habrá un objeto DelegateRef maestro. Su matriz mantiene un registro de todos los delegateRefs que envuelven a los delegados reales. El propósito principal aquí es eliminar la fuerte referencia a delegateRefs mantenida por la matriz cuando los delegados reales se reparten. Por lo tanto, se crea un objeto de vigilancia local y se asocia para delegar cuando se agrega el delegado. Cuando el dealloc del reloj local, el delegateRef se elimina de la matriz del DelegateRef maestro.
#import <objc/runtime.h>
@interface WeakWatcher : NSObject
@property (nonatomic, weak) NSMutableArray *masterarray;
@property (nonatomic, weak) DelegateRef *delegateRef;
@end
@implementation WeakWatcher
-(void)dealloc
{ // when the object dealloc, this will be called
if(_delegateRef != nil)
{
if([self.masterarray containsObject:_delegateRef])
{
[_masterarray removeObject:_delegateRef];
}
}
}
@end
@interface DelegateRef()
@end
@implementation DelegateRef
static char assoKey[] = "assoKey";
- (NSMutableArray *)array {
if (_array == nil) {
_array = [NSMutableArray array];
}
return _array;
}
-(void)addWeakRef:(id)ref
{
if (ref == nil) {
return;
}
DelegateRef *delRef = [DelegateRef new];
WeakWatcher* watcher = [WeakWatcher new]; // create local variable
watcher.delegateRef = delRef;
watcher.masterarray = self.array;
[delRef setDelegateWeakReference:ref];
objc_setAssociatedObject(ref, assoKey, watcher, OBJC_ASSOCIATION_RETAIN);
[self.array addObject:delRef];
}
@end
¿Existe un mecanismo que permita a un objeto saber que una referencia débil de reducción a cero se volvió nula?
Por ejemplo tengo una propiedad
@property (nonatomic, weak) MyClass *theObject;
cuando theObject se desasigna y la propiedad se vuelve nula, quiero que se me notifique. ¿Pero cómo? ¿El sistema de referencia débil de puesta a cero usa el setter para establecer la propiedad en nulo cuando el objeto desaparece?
El tiempo de ejecución simplemente establece el ivar débil _theObect en nil, no se llama a un configurador personalizado.
Qué podría hacer (si realmente necesita la notificación):
- definir una clase de "observador" local e implementar dealloc en esa clase,
- cree un objeto de observador y configúrelo como "objeto asociado" de _theObject.
Cuando _theObject se desasigna, el objeto asociado se libera y desasigna (si no hay otras referencias fuertes a él). Por eso se llama su método dealloc. Esta es tu "notificación".
(Estoy escribiendo esto en el teléfono y puedo completar los detalles más adelante si es necesario).
Implementé esto utilizando el llamado registro de referencia débil, vea la clase BMWeakReferenceRegistry , parte de mi marco de código abierto BMCommons para iOS.
Esta clase asocia objetos de contexto con el objeto de interés. Cuando este objeto se libera, también lo es el objeto de contexto y se llama al bloque de limpieza.
Ver la API:
/**
* Registry for monitoring the deallocation of objects of interest to perform cleanup logic once they are released.
*/
@interface BMWeakReferenceRegistry : BMCoreObject
BM_DECLARE_DEFAULT_SINGLETON
/**
* Cleanup block definition
*/
typedef void(^BMWeakReferenceCleanupBlock)(void);
/**
* Registers a reference for monitoring with the supplied cleanup block.
* The cleanup block gets called once the reference object gets deallocated.
*
* It is possible to register the same reference multiple times with different cleanup blocks (even if owner is the same).
* If this is not intended behavior, check hasRegisteredReference:forOwner: before calling this method.
*
* @param reference The object to monitor
* @param owner An optional owner (may be specified to selectively deregister references)
* @param cleanup The cleanup block
*/
- (void)registerReference:(id)reference forOwner:(id)owner withCleanupBlock:(BMWeakReferenceCleanupBlock)cleanup;
/**
* Deregisters the specified reference for monitoring. If owner is not nil, only the monitor(s) for the specified owner is/are removed.
*
* @param reference The monitored reference
* @param owner The optional owner of the reference
*/
- (void)deregisterReference:(id)reference forOwner:(id)owner;
/**
* Checks whether a monitor already exists for the specified reference/owner. If the owner parameter is nil all owners are checked.
*
* @param reference The monitored reference
* @param owner The optional owner
* @return True if registered, false otherwise.
*/
- (BOOL)hasRegisteredReference:(id)reference forOwner:(id)owner;
@end
No hay notificación sobre la desasignación de objetos.
El sistema no utilizará el método de establecimiento (esto significa que no se generarán notificaciones de KVO). El ivar es la referencia débil real que se pone a cero. La palabra clave weak
en una propiedad es simplemente una instrucción para sintetizar el ivar y una declaración pública de que el objeto no se conserva.
Aunque siempre puede inventar sus propias notificaciones y enviarlas desde el método dealloc
de sus clases, tenga en cuenta que normalmente no debería estar interesado en tales notificaciones y que hay al menos una buena razón por la que no existen.
Siempre que haya algún tipo de gestión de memoria automática en uso, no puede (por definición) esperar que los objetos mueran exactamente cuando los necesita, eso se aplica al conteo de referencias de Objective-C. Debido a que cualquier componente puede prolongar inesperadamente la vida útil de cualquier objeto por un período de tiempo desconocido, confiar en el comportamiento del programa suponiendo que se dealloc
exactamente cuando lo necesite, es un mal diseño y una receta para los problemas. dealloc
debe utilizar para la limpieza solamente.
Pruebe esta regla de oro: ¿el programa seguirá funcionando correctamente si no se llama en absoluto a dealloc
? Si no es así, debería reconsiderar la lógica del programa en lugar de enviar notificaciones de dealloc.
Si te importa cuando un objeto desaparece, no debes usar una referencia débil. ¿Que estás tratando de hacer?
no hay sistema de notificación para vars débiles.