2008-08-17 14 views

Respuesta

38

Necesita usar -removeObserver:forKeyPath: para eliminar el observador antes de ejecutar -[NSObject dealloc], entonces sí, hacerlo en el método -dealloc de su clase funcionaría.

Mejor que eso sería tener un punto determinista donde lo que posee el objeto que está haciendo la observación podría decir que está hecho y (eventualmente) será desasignado. De esta forma, puede dejar de observar inmediatamente cuando ya no se necesita lo que está haciendo la observación, independientemente de cuándo se desasigna.

Esto es importante tener en cuenta porque la vida útil de los objetos en Cocoa no es tan determinista como algunas personas parecen pensar que es. Los diversos frameworks de Mac OS X en sí mismos serán y enviarán sus objetos -retain y -autorelease, extendiendo su vida más allá de lo que de otro modo podrían pensar que sería.

Por otra parte, cuando se hace la transición a la recolección de basura de Objective-C, usted encontrará que -finalize se ejecutará en momentos muy diferentes - y en muy diferentes contextos - -dealloc que lo hicieron. Por un lado, la finalización tiene lugar en un hilo diferente, por lo que realmente no puede enviar de forma segura -removeObserver:forKeyPath: a otro objeto en un método -finalize.

palillo de la memoria (y otros recursos escasos) en la gestión -dealloc y -finalize, y utilizar un método separado -invalidate tener un propietario indicar a un objeto que haya terminado con él en un punto determinista; hacer cosas como eliminar las observaciones de KVO allí. La intención de su código será más clara y tendrá menos errores sutiles de los que ocuparse.

+7

puedo confirmar por experiencia que el dolor que va a recibir en un sinfín de accidentes si no se retiran a sus observadores. – Jeff

+0

¡Gracias por esa minuciosa explicación! –

+0

A partir de OS X 10.7 Lion, también hay '-removeObserver: forKeyPath: context:', que le permite pasar en el mismo contexto que pasó a '-addObserver: forKeyPath: options: context:'. Pasar un contexto único garantiza que no eliminará la observación de otra persona cuando elimine la suya.En caso que –

5

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

+0

está documentado el lugar? – hpique

2

Definitivamente estoy de acuerdo con Chris en el comentario "Stick to memory (y otros recursos escasos) en -dealloc and -finalize ...". Muchas veces veré que las personas intentan invalidar los objetos NSTimer en sus funciones dealloc. El problema es que NSTimer retiene sus objetivos. Entonces, si el objetivo de ese NSTimer es uno mismo, dealloc nunca será llamado, lo que dará como resultado pérdidas de memoria potencialmente desagradables.

Invalidate en -invalidate y hacer otra limpieza de la memoria en su dealloc y finalize.

Cuestiones relacionadas