2013-01-16 16 views
5

Diciamo che ho:KVO e refactoring

@property NSNumber* number; 

E il mio controller sta osservando:

- (void)observeValueForKeyPath:(NSString *)keyPath ... 
{ 
    if ([keyPath isEqualToString:@"number"]) ... 
} 

La mia domanda è - che cosa è il vostro approccio al refactoring del nome della proprietà number?

È ovvio che ho bisogno di aggiornare la chiave osservata nel codice degli osservatori, ma come potrei farlo in qualche modo intelligente/automatico, e non mi manca nessun osservatore che guarda per gestire il cambiamento della mia proprietà?

+0

Cosa si desidera per il refactoring? Non vedo nemmeno il codice effettivo che fa qualcosa. –

+0

Mi spiace, ho appena aggiornato, intendevo ridenominare la proprietà e aggiornare il nome keyPath osservato –

risposta

3

Un modo è quello di dichiarare costanti di stringa per tutte le proprietà che vengono osservate. Utilizzare queste costanti per aggiungere osservatore e confrontare keypath. È necessario modificare il valore di tali costanti stringa ogni volta che si desidera rinominare la proprietà.

Non penso che l'atomizzazione completa sia possibile.

+0

Sì, ci stavo pensando, è ancora impegnativo;) –

+0

Un altro modo è usare la riflessione.Se è corretto che il numero di proprietà e il suo ordine nella classe non cambieranno, puoi avvalerti delle funzioni di runtime come accedere alla proprietà di un particolare indice. – Apurv

3

Ok, risponderò a me stesso :) La mia soluzione è un mix di soluzioni Apurv e test di unità.

qui è:

Per ogni proprietà osservate in MyClass definiscono:

static NSString* MyClassPropertyNameNumber = @"number";

In - (void)observeValueForKeyPath:(NSString *)keyPath ... uso attuazione solo NSStrings definiti.

- (void)observeValueForKeyPath:(NSString *)keyPath ... 
{ 
    if ([keyPath isEqualToString:MyClassPropertyNameNumber]) ... 
} 

Mandaci il test di unità che controllerà se oggetto MyClass risponde setNumber: e number selettori.

- (void)testMyClass 
{ 
    SEL numberGetter = NSSelectorFromString(MyClassPropertyNameNumber); 
    SEL numberSetter = NSSelectorFromString([NSString stringWithFormat:@"set%@:", MyClassPropertyNameNumber]); 

    MyClass* testMyClass = [[MyClass alloc] init]; 
    if (![testMyClass respondsToSelector:numberGetter] || ![testMyClass respondsToSelector:numberSetter]) 
    { 
     STFail(@"%@: %@ property name has changed! Please update your defined property name!", NSStringFromClass([MyClass class]), MyClassPropertyNameNumber); 
    } 
} 

Non funzionerà se cambi il nome della proprietà e non aggiorni il nome della proprietà definita.

spero che sarà utile per qualcuno :)

1

definire una variabile per ogni percorso chiave osservati, li usano come contesti al momento della registrazione e nel metodo del gestore osservatore:

static void * numberKVO = &numberKVO; 
static void * letterKVO = &letterKVO; 

... 
[self addObserver:self 
     forKeyPath:@"kp.4.number" 
      options:NSKeyValueObservingOptionNew 
      context:numberKVO]; 
[self addObserver:self 
     forKeyPath:@"kp.4.letter" 
      options:NSKeyValueObservingOptionNew 
      context:letterKVO]; 
... 

- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 
    if (context == numberKVO) { 
     ... 
    } else if (context == letterKVO) { 
     ... 
    } 
} 

È possibile modificare le proprietà e i percorsi chiave senza cambiare altro.

0

Mogenerator è un ottimo strumento per gestire le classi di modelli di Core Data. Genera NSStrings per tutti gli attributi, le relazioni e le proprietà recuperate in:

extern const struct ModelClassAttributes 
extern const struct ModelClassRelationships 
extern const struct ModelClassFetchedProperties