2012-05-04 13 views
5

Supongamos que tengo una clase con una propiedad de solo lectura.Si escribo un método getter de propiedad personalizado, ¿KVO seguirá funcionando si el getter devuelve un valor accediendo a un valor de otro objeto?

//MyClass.h 
@interface MyClass 

@property (readonly) NSInteger MonitorMe; 

@end 

Ahora, vamos a suponer el punto de esta propiedad es para controlar los cambios de otra propiedad, dentro de otro objeto, y cuando se "observa" la propiedad devuelve un valor derivado mediante la inspección de un valor de la otra, externa objeto.

//MyClass.m 
@implementation 

@synthesize MonitorMe; 
-(NSInteger) getMonitorMe 
{ 
    return globalStaticClass.OtherNSInteger; 
} 

... Inits and Methods ... 
@end 

Ahora, vamos a suponer que algunos donde se crea una instancia del objeto MyClass, y quiero añadir un observador MVA en la propiedad MonitorMe.

//AnotherClass.m 
@implementation AnotherClass.m 

    @synthesize instanceOfMyClass; 

    -(id)init 
    { 
     ... 
     instanceOfMyMethod = [MyClass init]; 
      [MyClass addObserver: self 
        forKeyPath: @"MonitorMe" 
        options: NSKeyValuObservingOptionNew 
        context: nil]; 
     ... 
    } 

Mi pregunta es, ya que la propiedad MonitorMe sólo supervisa los cambios de valores en un objeto externo, será el método de observador ejecutará cuando el valor de globalStaticClass.OtherNSInteger cambios? Además, si la respuesta es sí, ¿cómo se hace esto?

Si esto funciona, me parecería un vudú de compilación.

Nota

no creo que se hace una diferencia, pero yo estoy usando ARC para esta aplicación y estoy compilación de un dispositivo iOS. Dudo que existan diferencias de compilación entre OS X e iOS para este tipo de preguntas, pero, si es importante, tengo un proyecto de iOS que requiere una implementación como la descrita anteriormente.

Además, el ejemplo descrito anteriormente es una configuración muy básica de mis necesidades reales. Se podría argumentar que podría/debería agregar una observación al valor globalStaticClass.OtherNSInteger en lugar de la propiedad de solo lectura, MonitorMe. En mi circunstancia real, esa respuesta no es suficiente porque mi propiedad de solo lectura es mucho más compleja que mi ejemplo.

Respuesta

8

¿Se ejecutará el método del observador cuando cambie el valor de globalStaticClass.OtherNSInteger?

No, pero puede a que esto suceda, a través de +keyPathsForValuesAffectingMonitorMe (o el más genérico +keyPathsForValuesAffectingValueForKey:, si el "globalStaticClass" es en realidad una propiedad de MiClase. Ver "Registering Dependent Keys" en la Guía de MVA.

Aquí es una maqueta rápida:

#import <Foundation/Foundation.h> 

@interface Monitored : NSObject 
@property NSInteger otherInteger; 
@end 

@implementation Monitored 
@synthesize otherInteger; 
@end 

@interface Container : NSObject 
@property (readonly) NSInteger monitorMe; 
@property (strong) Monitored * theMonitored; 

- (void)changeMonitoredInteger; 
@end 

@implementation Container 

@synthesize theMonitored; 

+ (NSSet *)keyPathsForValuesAffectingMonitorMe { 

    return [NSSet setWithObject:@"theMonitored.otherInteger"]; 
} 

- (id) init { 

    self = [super init]; 
    if(!self) return nil; 

    theMonitored = [[Monitored alloc] init]; 
    [theMonitored setOtherInteger:25]; 

    return self; 
} 

- (NSInteger)monitorMe 
{ 
    return [[self theMonitored] otherInteger]; 
} 

- (void)changeMonitoredInteger { 

    [[self theMonitored] setOtherInteger:arc4random()]; 
} 

@end 

@interface Observer : NSObject 
@end 

@implementation Observer 

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 

    NSLog(@"Observing change in: %@ %@", keyPath, object); 
} 

@end 

int main(int argc, const char * argv[]) 
{ 

    @autoreleasepool { 

     Observer * o = [[Observer alloc] init]; 
     Container * c = [[Container alloc] init]; 

     [c addObserver:o 
      forKeyPath:@"monitorMe" 
       options:NSKeyValueObservingOptionNew 
       context:NULL]; 

     [c changeMonitoredInteger]; 
     [c changeMonitoredInteger]; 

    } 
    return 0; 
} 

notas de estilo PS cacao: propiedades/variables deben tienen letras iniciales en minúscula, y (esto es en realidad más importante ahora debido a la ARC) no nombra a métodos de acceso a Comience con "obtener", que tiene un significado específico en Cocoa que implica pasar en un búfer y recuperar datos por referencia.

+0

¡No me di cuenta de que los métodos de nomenclatura con "get" en ARC eran un problema! Sí, necesito volver a escribir algunos códigos ahora. ¡Gracias! – RLH

+0

Para ser completamente justo, no estoy absolutamente seguro de que cause problemas, pero esa es una convención muy bien establecida en Cocoa, y sé que ARC utiliza nombres de métodos para razonar sobre la gestión de los valores de devolución. –

+0

Jacques: publicó un enlace de arriba que parece ser específico de OS X 10.4 y 10.5. ¿La información también es relevante para iOS 5.1? – RLH

Cuestiones relacionadas