2010-11-10 3 views
14

Ich habe zwei Klassen in meiner App-Klasse A und B. Beide Klassen A und B sind Instanzen von UIViewController. Klasse A hat eine Schaltfläche, die beim Drücken die Klasse B auf den Stapel verschiebt. Klasse B hat eine Zeichenkette, die die Klasse A bei Bedarf beobachten und aktualisieren möchte. Ich konnte verwenden: [self addObserver:self forKeyPath:@"name" options:0 context:NULL]; in Klasse B, um die Änderungen an der Zeichenfolge anzuzeigen. Wenn ich versuche, die folgenden in der Klasse A viewWillAppear Methode verwenden:iPhone KVO zwischen zwei Klassen

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

und fügen Sie die Methode:

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

keine Aktion ausgelöst wird, wenn die vorgenommene Aktualisierungen in B von A zu sehen versuche ich fühle mich albern diese Frage zu stellen, aber wie funktioniert KVO zwischen zwei Klassen in iOS? Ich weiß, das sollte funktionieren.

Antwort

38

Sie können Änderungen über verschiedene Objekte/Klassen beobachten. Ich denke, das Problem ist in den Optionen Parameter addObserver:forKeyPath:options:context:.

Es gibt verschiedene Optionen für die Art der Beobachtung, die Sie durchführen möchten. Die KVO Guide ist ein guter Ausgangspunkt, aber Sie wollen wahrscheinlich NSKeyValueObservingOptionNew, die ich im folgenden Beispiel verwenden.

Zuerst sollte "name" eine öffentliche Eigenschaft in ClassB sein.

Zweitens müssen Sie den Observer wahrscheinlich nicht zu "b" in viewWillAppear in ClassA hinzufügen, da Sie ihn nicht jedes Mal hinzufügen müssen, wenn die ClassA-Ansicht angezeigt wird. Sie müssen den Beobachter nur einmal hinzufügen, wenn Sie die ClassB-Ansicht erstellen. Sobald Sie den Observer hinzugefügt haben, wird die observeValueForKeyPath:ofObject:change:context:-Methode in ClassA ausgeführt, sodass Sie von dort aus die Aktualisierung auf die ClassA-Benutzeroberfläche vornehmen können. Sie sollten nicht jedes Mal etwas tun müssen, wenn ClassA erscheint.

In Klasse A sollten Sie wahrscheinlich ClassB erstellen, bevor Sie ClassB auf den Controller-Stack schieben, vermutlich in der Ereignisbehandlungsroutine für eine Aktion, die der Benutzer nahm. Fügen Sie den Observer in ClassA unmittelbar nach dem Erstellen von ClassB mit dem richtigen NSKeyValueObservingOption-Wert hinzu.

Wenn Sie wollen einfach nur, wenn der "Name" öffentliches Eigentum mitgeteilt werden in ClassB geändert wird, dann ist dies versuchen:

ClassB

KlasseA

@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

Dies ist wahrscheinlich die Problem. Sie müssen den Parameter options verwenden, um anzugeben, welche Benachrichtigungen Sie wünschen. Wenn Sie 0 eingeben, werden Sie nicht um etwas gebeten. – benzado

+0

nekno, Danke für die Hilfe! – fmcauley

+6

Wenn dies jemand hilft, hatte ich ein Problem, wo meine "observeValueForKeyPath" Nachricht nicht ausgelöst wurde, obwohl ich es fast genau wie nekno geschrieben habe. Sie müssen die Eigenschaft mit self.name = newvalue, * NOT * nur name = newvalue ändern. – Mirkules