2008-10-03 6 views
13

Estoy acostumbrado a codificar UIs Java Swing, y en esas si tiene algunas propiedades que cambian y desea que su UI se actualice, usted implementaría el patrón observador/observable. En Java haces esto normalmente haciendo que tu clase mantenga una lista de oyentes que notifica de diferentes eventos.¿Cuál es la mejor manera de hacer observador/observable en Object-C (versión iphone)

He jugado con Objective-C en la Mac, y eso tiene KVC y enlace que parece funcionar muy bien y requiere menos código. Sin embargo, el iPhone SDK no parece tener esta funcionalidad, por lo que mi pregunta es: Si tengo una clase que contiene datos que cambian, ¿cuál es la mejor manera de registrar un componente UI con esa clase para que se pueda notificar? de cambios en los datos que necesita mostrar?

Respuesta

37

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.

+4

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

+0

@TIMM: Llamaría al método apropiado para el objeto observado. Por ejemplo: '[self removeObserver: theObserver forKeyPath: @" someProperty "];' – FreeAsInBeer

+0

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. –

0

Por lo general, no es la forma en que se hace. Eche un vistazo a la discusión here, en particular, el enlace a la documentación de Apple.

Si aún desea hacerlo de la forma en que dice que lo hace, no es particularmente difícil implementar algo así como los enlaces "a mano". Simplemente creará un objeto "vinculante" que sepa cómo suscribirse a los cambios y se conecte a una propiedad de una vista.

Para responder realmente cómo se hace, normalmente tiene un objeto controlador que supervisa el estado del modelo (que actúa como un observador) y actualiza los objetos de visualización según sea necesario.

+0

Sólo estoy preguntando qué es lo mejor y dando un ejemplo de JAVA. No estoy particularmente preocupado si la forma de Objective-C es totalmente diferente, solo quiero saber de qué se trata. – rustyshelf

+0

Lo tengo. Edité mi respuesta para aclarar a qué me refería. –

9

También encontré que usted puede hacer:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleWhateverChange) name:@"whateverChange" object:nil]; 

Para registrarse para los eventos de cambio, y

[[NSNotificationCenter defaultCenter] postNotificationName:@"whateverChange" object:nil]; 

Para disparar ellos.Podría ser un N00b pero no pude lograr que el observador de la ruta clave funcionara para mí.

Cuestiones relacionadas