Hay dos formas integradas de observación en Cocoa: observación de valores-clave y notificaciones. En ninguno de los sistemas, necesita mantener o notificar a una colección de observadores usted mismo; el marco lo manejará por ti.
Observación de valores-clave (KVO) le permite observar una propiedad de un objeto, incluso una propiedad que representa una colección, y recibir notificaciones de cambios en esa propiedad. Solo debe enviar el objeto -addObserver:forKeyPath:options:context:
pasando el objeto que desea recibir actualizaciones, la ruta de la clave de la propiedad (relativa al receptor) para la que desea recibir actualizaciones y los tipos de actualizaciones que desea recibir. (Hay métodos similares que puede usar si desea observar una propiedad que representa una colección.)
Las notificaciones son más antiguas y de mayor peso. Se registra con un NSNotificationCenter
, generalmente el centro predeterminado, un objeto y un par de selector para recibir una notificación cuando ocurre un evento. El objeto de notificación en sí mismo puede contener datos arbitrarios a través de su propiedad userInfo
, y puede optar por observar todas las notificaciones de un nombre específico en lugar de las que se aplican a un objeto particular.
¿Cuál debería usar en cualquier caso en particular? En general, si le importan los cambios en una propiedad específica de un objeto específico, use Observación de valores-clave. Para eso está diseñado y es intencionalmente liviano. (Entre otros usos, es la base sobre la que se construyen los enlaces de cacao). Si le importa un cambio en el estado que no está representado por una propiedad, entonces las notificaciones son más apropiadas.
Por ejemplo, para mantener la sincronización cuando el usuario cambia el nombre de un objeto modelo, usaría KVO. Para saber cuándo se guardó un gráfico completo de objetos, usaría las notificaciones.
Excelente respuesta, pero con el enfoque de KVO, ¿cómo se elimina a un observador que se ha registrado en muchos objetos? Pensé (erróneamente) que KVO usó las notificaciones bajo el capó, pero no creo que lo haga. Por lo tanto, después de usar addObserver: X forKeyPath: ..., si lo intenta hacer más tarde: [[NSNotificationCenter defaultCenter] removeObserver: X] esto no funciona? Parece implicar que debe mantener una lista separada de todos los objetos que X está observando para poder eliminar la observación. ¿O me estoy perdiendo algo? – TimM
@TIMM: Llamaría al método apropiado para el objeto observado. Por ejemplo: '[self removeObserver: theObserver forKeyPath: @" someProperty "];' – FreeAsInBeer
Nuevo en OS X 10.7 Lion e iOS 5.0, hay un método -removeObserver: forKeyPath: context: al que puede pasar el mismo contexto que pasó cuando agregando el observador. Debería hacer eso siempre que sea posible, en caso de que varios objetos estén observando la misma ruta de tecla. –