type observer notification non cannot ios model-view-controller delegates key-value-observing nsnotificationcenter

observer - Observando cambios en una matriz mutable usando KVO vs. NSNotificationCenter



swift 4 nsnotificationcenter (2)

De acuerdo con los documentos sobre métodos de acceso , debe implementar:

- (void)addEventsObject:(Event*)e { [_events addObject:e]; } - (void)removeEventsObject:(Event*)e { [_events removeObject:e]; }

Entonces KVO disparará las notificaciones cuando se llamen.

En mi modelo tengo una matriz de objetos llamados eventos. Deseo que se notifique a mi controlador cada vez que se agregue un nuevo objeto a los eventos.

Pensé que una buena manera de hacer esto sería usar el patrón KVO para recibir notificaciones cuando los eventos cambian (de un nuevo objeto que se agrega)

// AppDelegate // events is a NSMutableArray @property/@synthesize etc... [appDelagate addObserver:self forKeyPath:@"events" options:NSKeyValueObservingOptionNew context:NULL];

Pero el método observeValueForKeyPath no estaba siendo llamado y descubrí que las matrices no son compatibles con KVO :-(

Una opción es activar manualmente el método llamando a willChangeValueForKey para el keyPath

// ViewController [self willChangeValueForKey:@"events"]; [self.events addObject:event]; [self didChangeValueForKey:@"events"];

Pero esto me parece pesado, ya que probablemente también debería hacer un seguimiento del estado anterior y posterior de la matriz de eventos para que se pueda acceder desde el método observeValueForKeyPath .

Un enfoque podría ser usar una matriz estándar (en lugar de mutable) y crear / establecer una nueva instancia de eventos cada vez que quiera agregar un nuevo objeto, o podría hacer una propiedad separada que haga un seguimiento de cuántos elementos hay en el matriz mutable (me gustaría que pudieras observar @ "events.count").

Otra opción sería utilizar NSNotificationCenter. También he leído algunas respuestas que sugieren el uso de bloques (pero no tengo idea de por dónde empezar).

Finalmente, ¿podría mantener una instancia de mi controlador en mi delegado y simplemente enviar un mensaje relevante?

// Delegate [myController eventsDidChange];

¿Es extraño mantener una referencia a un controlador de un delegado?

Estoy luchando para entender cómo elegir cuál es el mejor enfoque de uso, por lo que cualquier consejo sobre rendimiento, flexibilidad de código futuro y mejores prácticas son muy apreciados.


No debe hacer propiedades públicas directas para colecciones mutables para evitar que se muten sin su conocimiento. NSArray no es un valor clave observable en sí mismo, pero su propiedad uno-a-muchos @"events" es. Aquí está cómo observarlo:

Primero, declare una propiedad pública para una colección inmutable:

@interface Model @property (nonatomic, copy) NSArray *events; @end

Luego, en su implementación, respóndalo con un ivar mutable:

@interface Model () { NSMutableArray *_events; } @end

y anular el getter y setter:

@implementation Model @synthesize events = _events; - (NSArray *)events { return [_events copy]; } - (void)setEvents:(NSArray *)events { if ([_events isEqualToArray:events] == NO) { _events = [events mutableCopy]; } } @end

Si otros objetos necesitan agregar eventos a su modelo, pueden obtener un objeto de proxy mutable llamando a -[Model mutableArrayValueForKey:@"events"] .

NSMutableArray *events = [modelInstance mutableArrayValueForKey:@"events"]; [events addObject:newEvent];

Esto activará las notificaciones de KVO al establecer la propiedad con una nueva colección cada vez. Para un mejor rendimiento y un control más granular, implemente el resto de los accesores de matriz .

Vea también: Observar un NSMutableArray para inserción / remoción .