2010-11-10 13 views
14

J'ai deux classes dans mon application classe A et classe B. Les classes A et B sont des instances de UIViewController. La classe A a un bouton qui, poussé, pousse la classe B sur la pile. La classe B a une chaîne que la classe A aimerait observer et mettre à jour son interface au besoin. J'ai été en mesure d'utiliser: [self addObserver:self forKeyPath:@"name" options:0 context:NULL]; dans la classe B pour afficher les modifications apportées à la chaîne. Quand j'essaie d'utiliser ce qui suit dans la classe Méthode viewWillAppear:iPhone KVO entre deux classes

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

et ajouter la méthode:

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

Aucune action est déclenché lorsque vous essayez d'afficher les mises à jour effectuées dans B de A. I se sentir bête en posant cette question, mais comment fonctionne KVO entre deux classes dans iOS? Je sais que ça devrait marcher.

Répondre

38

Vous pouvez observer les modifications entre différents objets/classes. Je pense que le problème est dans le paramètre options de addObserver:forKeyPath:options:context:.

Il existe différentes options pour le type d'observation que vous voulez faire. Le KVO Guide est un bon point de départ, mais vous voulez probablement NSKeyValueObservingOptionNew, que j'utilise dans l'exemple ci-dessous. D'abord, "name" doit être une propriété publique dans ClassB. Deuxièmement, vous n'avez probablement pas besoin d'ajouter l'observateur à "b" dans viewWillAppear dans ClassA, car vous n'avez pas besoin de l'ajouter chaque fois que la vue ClassA va apparaître. Vous avez juste besoin d'ajouter l'observateur une fois, lorsque vous créez la vue ClassB. Une fois que vous avez ajouté l'observateur, la méthode observeValueForKeyPath:ofObject:change:context: sera exécutée dans ClassA, vous pouvez donc effectuer la mise à jour vers l'interface utilisateur ClassA à partir de là. Vous ne devriez rien faire à chaque fois que ClassA est sur le point d'apparaître.

Dans la classe A, vous devez probablement créer ClassB juste avant de pousser ClassB sur la pile du contrôleur, vraisemblablement dans le gestionnaire d'événements pour une action prise par l'utilisateur. Immédiatement après avoir créé ClassB, ajoutez l'observateur dans ClassA avec la valeur NSKeyValueObservingOption correcte.

Si vous voulez juste pour être informé chaque fois que change la propriété publique "nom" dans ClassB, essayez ceci:

ClassB

ClassA

@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

C'est probablement la problème. Vous devez utiliser le paramètre options pour indiquer les notifications que vous souhaitez. En passant à 0, vous ne demandez pas d'être averti de quoi que ce soit. – benzado

+0

nekno, Merci pour l'aide! – fmcauley

+6

Si cela aide quelqu'un, j'ai eu un problème où mon message observeValueForKeyPath ne tirait pas, même si je l'ai écrit presque exactement le même que nekno. Vous * AVEZ * pour changer la propriété en utilisant self.name = newvalue, * NOT * juste name = newvalue. – Mirkules