87

¿Cómo se elimina un observador de un objeto en ARC? ¿Acabamos de agregar al observador y olvidarnos de eliminarlo? Si ya no gestionamos la memoria manualmente, ¿dónde renunciamos a la observación?KVO y ARC cómo quitar Observer

Por ejemplo, en un controlador de vista:

[self.view addObserver:self 
      forKeyPath:@"self.frame" 
       options:NSKeyValueObservingOptionNew 
       context:nil]; 

Anteriormente, yo llamaría removeObserver: en el método de la controlador de vista dealloc.

+4

Tenga en cuenta que se trata de una muy mala idea MVA .Frame. Según lo escrito por los ingenieros de Apple en StackOverflow, la propiedad de marco de UIKit no es compatible con KVO. Cuando funciona, es solo por pura casualidad. – steipete

+2

¿No debería su keyPath ser '@" frame "' en lugar de '@" self.frame "'? – Besi

Respuesta

126

Aún puede implementar -dealloc en ARC, que parece ser el lugar apropiado para eliminar la observación de valores clave. Simplemente no llame al [super dealloc] desde este método más.

Si estaba anulando -release antes, estaba haciendo las cosas mal.

+1

¿Estás seguro de esto? Cito de http://clang.llvm.org/docs/AutomaticReferenceCounting.html#ownership.spelling.property, sección 7.1.2. dealloc: "Justificación: aunque ARC destruye variables de instancia automáticamente, todavía hay razones legítimas para escribir un método dealloc, como liberar recursos no retenibles. No poder llamar a [super dealloc] en un método así es casi siempre un error". –

+0

@ElisevanLooij Sí, eso es cierto. Si deriva de esta clase, parece obvio que debe llamar a '[super dealloc]'. ¿Quién más debería hacer esto por ti? –

+0

@ElisevanLooij Oops, bueno, debería haberlo hecho antes. No está permitido llamar '[super dealloc]' en un método dealloc. No tengo idea de cómo funcionaría esto cuando se subclasifica la clase mencionada. Tal vez sea aconsejable utilizar 'finalize' en su lugar (donde se llama' [super finalize] ') –

-2

Elsewhere en desbordamiento de pila, Chris Hanson aconseja usar el método de finalización para este fin y aplicar un método de invalidación separado para que los propietarios puedan decirles a los objetos que están hechos. En el pasado, he encontrado que las soluciones de Hanson están bien pensadas, así que iré con eso.

+13

Tenga en cuenta que se estaba refiriendo a la recolección de basura allí, no a ARC (su respuesta fue escrita en 2008). En la recolección de basura, '-dealloc' nunca se llama. En ARC, lo es. Es perfectamente aceptable eliminar observadores de KVO en '-dealloc', como indica Chris Lattner (quién sabe de lo que habla) en los foros de desarrolladores de Apple aquí: https://devforums.apple.com/message/475850 –

+3

Gracias Brad, por hacer todo este trabajo No para finalizar, sí para dealloc pero sin [super dealloc]. Simple realmente, una vez que lo sabes. ¡Oye, @drunknbass, acepta la respuesta de ese hombre! –

0

lo hago con este código

- (void)dealloc 
{ 
@try{ 
    [self.uAvatarImage removeObserver:self forKeyPath:@"image" context:nil]; 
} @catch(id anException) { 
    //do nothing, obviously it wasn't attached because an exception was thrown 
} 
}  
+2

¿Cuál es el punto de manejo de excepciones en 'dealloc'? Es muy tarde para hacer algo al respecto. – Abizern

+0

¿Cuál es el punto de eliminar observadores en una variable de instancia en dealloc? Este uAvatarImage será desasignado pronto junto con cualquier observador que se haya suscrito a sus rutas clave. – shoumikhin

+0

@shoumikhin Estoy usando ARC y tuve que eliminar al observador en el método dealloc. Tengo la misma pregunta que tienes. Sin embargo, cuando ejecuté varias instancias de la clase, finalmente obtuve el error exc_bad_address. Hacer esto resolvió el problema. Además, la respuesta desde aquí http://stackoverflow.com/questions/32490808/com-apple-nsurlsession-work-exc-bad-access-crash-debugging me ayudó a descubrir el problema. – mac10688