2010-11-10 5 views
14

Ho due classi nella mia classe di app A e di classe B. Entrambe le classi A e B sono istanze di UIViewController. La Classe A ha un pulsante che quando premuto spinge la classe B in pila. La classe B ha una stringa che la classe A vorrebbe osservare e aggiornare con la sua interfaccia secondo necessità. Sono stato in grado di utilizzare: [self addObserver:self forKeyPath:@"name" options:0 context:NULL]; in classe B per visualizzare le modifiche alla stringa. Quando provo e uso il seguente in classe metodo A viewWillAppear:iPhone KVO tra due classi

ClassB *b = [[ClassB alloc]init]; 
[b addObserver:self forKeyPath:@"name" options:0 context:NULL]; 

e aggiungi il metodo:

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

Nessuna azione viene licenziato quando si cerca di visualizzare gli aggiornamenti effettuati in B da A. sentirsi sciocco a fare questa domanda, ma come funziona KVO tra due classi in iOS? So che questo dovrebbe funzionare.

risposta

38

È possibile osservare i cambiamenti tra diversi oggetti/classi. Penso che il problema sia nel parametro options di addObserver:forKeyPath:options:context:.

Ci sono varie opzioni per il tipo di osservazione che si desidera eseguire. Il KVO Guide è un buon punto di partenza, ma probabilmente vuoi lo NSKeyValueObservingOptionNew, che uso nell'esempio qui sotto.

In primo luogo, "nome" deve essere una proprietà pubblica in ClassB.

In secondo luogo, probabilmente non è necessario aggiungere l'osservatore a "b" in viewWillAppear in ClassA, perché non è necessario aggiungerlo ogni volta che viene visualizzata la vista ClassA. Devi solo aggiungere l'osservatore una volta, quando crei la vista ClassB. Dopo aver aggiunto l'osservatore, il metodo observeValueForKeyPath:ofObject:change:context: verrà eseguito in ClassA, quindi puoi eseguire l'aggiornamento dall'interfaccia utente ClassA da lì. Non dovresti fare nulla ogni volta che ClassA sta per apparire.

In Classe A, probabilmente dovresti creare ClassB appena prima di andare a spingere ClassB nello stack del controller, presumibilmente nel gestore di eventi per qualche azione eseguita dall'utente. Subito dopo aver creato ClassB, aggiungi l'osservatore in ClassA con il valore NSKeyValueObservingOption corretto.

Se si desidera solo per essere avvisato ogni volta che la proprietà pubblica "nome" in ClassB è cambiato, quindi provare questo:

ClassB

ClasseA

@interface ClassA : UIViewController { 
} 

@property (nonatomic, retain) IBOutlet UILabel* nameLabel; 

- (IBAction) someEventHandler:(id)sender; 

@end 

@implementation ClassA 

- (IBAction) someEventHandler:(id)sender { 
    ClassB* b = [[ClassB alloc]init]; 
    [b addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:NULL]; 
    [self.navigationController pushViewController:b animated:YES]; 
    [b release]; 
} 

- (void) observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context { 
    if ([keyPath isEqual:@"name"]) { 
     NSString* changedName = [change objectForKey:NSKeyValueChangeNewKey]; 
     // do something with the changedName - call a method or update the UI here 
     self.nameLabel.text = changedName; 
    } 
} 

@end 
+0

Questo è probabilmente il problema. Devi usare il parametro options per indicare quali notifiche vuoi. Passando da 0, non stai chiedendo di essere avvisato di nulla. – benzado

+0

nekno, Grazie per l'aiuto! – fmcauley

+6

Se questo aiuta qualcuno, ho avuto un problema in cui il mio messaggio observValueForKeyPath non è stato attivato, anche se l'ho scritto quasi esattamente come nekno. È * HAVE * per modificare la proprietà utilizzando self.name = newvalue, * NOT * just name = newvalue. – Mirkules