2012-05-04 11 views
5

Supponiamo di avere una classe con una proprietà readonly.Se scrivo un metodo getter di proprietà personalizzato, KVO continuerà a funzionare se il getter restituisce un valore accedendo a un valore da un altro oggetto?

//MyClass.h 
@interface MyClass 

@property (readonly) NSInteger MonitorMe; 

@end 

Ora, supponiamo che il punto di questa proprietà è quello di monitorare le variazioni di un altro immobile, all'interno di un altro oggetto, e quando la proprietà è "osservato" restituisce un valore derivato controllando un valore dall'altro, esterna oggetto.

//MyClass.m 
@implementation 

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

... Inits and Methods ... 
@end 

Ora, supponiamo che alcuni dove creo un'istanza dell'oggetto MyClass, e voglio aggiungere un osservatore KVO sulla proprietà MonitorMe.

//AnotherClass.m 
@implementation AnotherClass.m 

    @synthesize instanceOfMyClass; 

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

mia domanda è, poiché la proprietà MonitorMe monitora solo le modifiche di valori in un oggetto esterno, sarà il metodo osservatore eseguire quando il valore di globalStaticClass.OtherNSInteger cambiamenti? Inoltre, se la risposta è sì, come è fatto?

Se funziona, sembrerebbe un compilatore voodoo per me.

Nota

io non credo che fa la differenza, ma io sto usando ARC per questa implementazione e sto compilando per un dispositivo iOS. Dubito che ci siano differenze di compilazione tra OS X e iOS per questo tipo di domanda, ma, se è importante, ho un progetto iOS che richiede una tale implementazione descritta sopra.

Inoltre, l'esempio descritto sopra è una configurazione molto semplice delle mie reali esigenze. Si potrebbe obiettare che potrei/dovrei aggiungere un'osservazione al valore globalStaticClass.OtherNSInteger invece della proprietà readonly, MonitorMe. Nella mia circostanza attuale la risposta non è sufficiente perché la mia proprietà readonly è molto più complessa del mio esempio.

risposta

8

il metodo di osservazione verrà eseguito quando il valore di cambia?

No, ma è possibile realizzare questo obiettivo, tramite +keyPathsForValuesAffectingMonitorMe (o il più generico +keyPathsForValuesAffectingValueForKey:, se il "globalStaticClass" è in realtà una proprietà di MyClass. Vedere "Registering Dependent Keys" nella Guida KVO.

Ecco un rapido mockup:

#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; 
} 

PS cacao note di stile: le proprietà/variabili dovrebbero avere lettere iniziali minuscole, e (questo è in realtà più importante ora a causa di ARC) non nominare metodi di accesso a inizia con "get" - che ha un significato specifico in Cocoa che implica il passaggio in un buffer e il recupero dei dati per riferimento.

+0

Non mi sono reso conto che i metodi di denominazione con "get" in ARC erano un problema! Yikes, ho bisogno di riscrivere un codice ora. Grazie! – RLH

+0

Per essere completamente onesti, non sono assolutamente _certain_ che causerà problemi, ma questa è una convenzione molto consolidata in Cocoa, e so che ARC usa i nomi dei metodi per ragionare sulla gestione dei valori di ritorno. –

+0

Jacques: hai postato un link sopra che sembra essere specifico per OS X 10.4 e 10.5. Le informazioni si riferiscono anche a iOS 5.1? – RLH

Problemi correlati