openstreetmaps features ec2 describe aws cocoa key-value-observing key-value-coding

cocoa - features - aws ec2 describe instances



Key-Value-Observando una relaciĆ³n de muchos en Cocoa (3)

Intento que funcione la observación de valores-clave para un NSMutableArray. A continuación se muestra el archivo .h para MyObservee, la clase observada:

@interface MyObservee : NSObject { @private int someValue; @private NSMutableArray *someArray; } @property (readwrite,assign) int someValue; - (NSMutableArray *)someArray; @end

La clase MyObserver implementa observeValueForKeyPath: ofObject: change: context :. Así es como agrego el observador:

MyObservee *moe = [[MyObservee alloc] init]; MyObserver *mobs = [[MyObserver alloc] init]; [moe addObserver:mobs forKeyPath:@"someArray" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:NULL]; [moe.someArray addObject:@"hi there"];

¿Cómo es que el mensaje addObject: no se activa como un cambio en la ruta de la clave someArray? Tengo la sensación de que hay algo que no entiendo completamente aquí.


Necesita implementar los accesores de matriz indexados como se define en la guía de programación de KVC . Luego debe usar esos accesos para acceder a la matriz y la activación de KVO funcionará. También puede llamar a -mutableArrayValueForKey: y usar esa matriz para agregarObject: y tal, a su vez llamará a los métodos de acceso y también se producirá la activación de KVO. También hay accesadores configurados para su uso en NSSets, ver aquí y aquí .

Ejemplo:

@interface MyClass : NSObject { NSMutableArray *_orders; } @property(retain) NSMutableArray *orders; - (NSUInteger)countOfOrders; - (id)objectInOrdersAtIndex:(NSUInteger)index; - (void)insertObject:(id)obj inOrdersAtIndex:(NSUInteger)index; - (void)removeObjectFromOrdersAtIndex:(NSUInteger)index; - (void)replaceObjectInOrdersAtIndex:(NSUInteger)index withObject:(id)obj; @end


Desafortunadamente, las clases de NSArray son compatibles con KVO. Son compatibles con KVC, pero no puedes observarlos directamente como lo intentas hacer aquí. La forma más fácil de obtener esta funcionalidad sería usar un NSArrayController. El controlador NSArray cumple con KVO y lo alertará cuando se agreguen o eliminen elementos. En su ejemplo, se le notificará a su observador si realmente cambió la matriz en sí. Por ejemplo, si hiciste algo como esto:

[moe setSomeArray:[NSMutableArray array]];

Probablemente no es lo que querías en absoluto :) Solo como un lado, NSDictionary es en realidad compatible con KVO para que puedas usar eso, si lo deseas. O podría escribir una subclase contenedora de NSMutableArray que simplemente crea una matriz mutable real como su almacén de respaldo, pero simplemente reenvía todos los mensajes a ella, excepto addObject y removeObject que puede anular para activar las notificaciones.


¿Por qué pasas tu matriz privada a otro objeto? No es tan privado cuando dejas que otros objetos lo manejen.

Como dijo s-bug, debe implementar los accessors y usar mutableArrayValueForKey: para mutar la propiedad. Agrego que no debe exponer esa matriz privada en absoluto someArray método someArray debe devolver una copia inmutable de la matriz.

Además, llamo su atención sobre el comentario de Jason Coco sobre la respuesta de s-bug. Para parafrasearlo, probablemente debería usar un NSArrayController como un paso adicional de separación entre myObservee y myObserver . Esta es una muy buena sugerencia, y si no tiene una razón específica para observar directamente la propiedad, debe tomarla. (Entre los beneficios, puede usar enlaces para conectar vistas al nuevo controlador de matriz).