En Cocoa, ¿debo eliminar un objeto para que no reciba notificaciones de KVO al desasignarlo?

StackOverflow https://stackoverflow.com/questions/13927

  •  08-06-2019
  •  | 
  •  

Pregunta

Cuando he registrado un objeto foo recibir notificaciones KVO de otro objeto bar (usando addObserver:...), si luego desasigno foo ¿Necesito enviar un removeObserver:forKeyPath: Mensaje para bar en -dealloc?

¿Fue útil?

Solución

Necesitas usar -removeObserver:forKeyPath: eliminar al observador antes -[NSObject dealloc] corre, así que sí, haciéndolo en el -dealloc El método de tu clase funcionaría.

Sin embargo, mejor que eso sería tener un punto determinista en el que quienquiera que sea el propietario del objeto que está realizando la observación podría decirle que ya está hecho y (eventualmente) será desasignado.De esa manera, puede dejar de observar inmediatamente cuando la cosa que realiza la observación ya no es necesaria, independientemente de cuándo se desasignó realmente.

Es importante tener esto en cuenta porque la vida útil de los objetos en Cocoa no es tan determinista como algunas personas parecen pensar.Los distintos marcos de trabajo de Mac OS X voluntad envía tus objetos -retain y -autorelease, extendiendo su vida más allá de lo que de otra manera podría pensar que sería.

Además, cuando realice la transición a la recolección de basura de Objective-C, encontrará que -finalize se ejecutará en momentos muy diferentes (y en contextos muy diferentes) que -dealloc hizo.Por un lado, la finalización se lleva a cabo en un hilo diferente, por lo que realmente no poder enviar de forma segura -removeObserver:forKeyPath: a otro objeto en un -finalize método.

Cíñete a la gestión de la memoria (y otros recursos escasos) en -dealloc y -finalize, y utilizar un separado -invalidate método para que un propietario le diga a un objeto que ha terminado con él en un punto determinista;haga cosas como eliminar las observaciones KVO allí.La intención de su código será más clara y tendrá menos errores sutiles que solucionar.

Otros consejos

Un poco de información adicional que obtuve gracias a una experiencia dolorosa:aunque NSNotificationCenter utiliza la puesta a cero de referencias débiles cuando se ejecuta bajo recolección de basura, KVO no lo hace.Por lo tanto, puede salirse con la suya sin eliminar un observador NSNotificationCenter cuando usa GC (cuando usa retener/liberar, aún necesita eliminar su observador), pero aún debe eliminar sus observadores KVO, como describe Chris.

Definitivamente estoy de acuerdo con Chris en el comentario "Cíñete a la gestión de la memoria (y otros recursos escasos) en -dealloc y -finalize...".Muchas veces veo personas intentar invalidar objetos NSTimer en sus funciones de asignación.El problema es que NSTimer conserva sus objetivos.Por lo tanto, si el objetivo de ese NSTimer es uno mismo, nunca se llamará a dealloc, lo que provocará algunas pérdidas de memoria potencialmente desagradables.

Invalidar en -invalidate y haz otra limpieza de memoria en tu dealloc y finalize.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top