IPhone KVO между двумя классами

У меня есть два класса в моем классе приложения A и классе B. Оба класса A и B являются экземплярами UIViewController. Класс A имеет кнопку, которая при нажатии на нее вытесняет класс B в стек. Класс B имеет строку, которую класс A хотел бы наблюдать и обновлять по мере необходимости. Я смог использовать: [self addObserver:self forKeyPath:@"name" options:0 context:NULL]; в классе B, чтобы просмотреть изменения в строке. Когда я пытаюсь использовать следующий метод класса viewWillAppear:

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

и добавьте метод:

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

При попытке просмотра обновлений, сделанных в B, никаких действий не предпринимается. Я чувствую себя глупо, задавая этот вопрос, но как KVO работает между двумя классами в iOS? Я знаю, что это должно работать.

Ответы

Ответ 1

Вы можете наблюдать изменения в разных объектах/классах. Я думаю, что проблема заключается в параметре параметров addObserver:forKeyPath:options:context:.

Существуют различные варианты того типа наблюдения, который вы хотите сделать. KVO Guide является хорошей отправной точкой, но вы, вероятно, хотите NSKeyValueObservingOptionNew, который я использую в приведенном ниже примере.

Во-первых, "имя" должно быть публичным свойством в ClassB.

Во-вторых, вам, вероятно, не нужно добавлять наблюдателя в "b" в viewWillAppear в ClassA, потому что вам не нужно добавлять его каждый раз, когда появится представление ClassA. Вам просто нужно добавить наблюдателя один раз, когда вы создаете представление ClassB. После добавления наблюдателя метод observeValueForKeyPath:ofObject:change:context: будет выполняться в ClassA, поэтому вы можете сделать обновление в пользовательском интерфейсе ClassA. Вам не нужно ничего делать каждый раз, когда появится ClassA.

В классе A вы, вероятно, должны создать ClassB только перед тем, как будете нажимать ClassB на стек контроллера, предположительно в обработчике событий для некоторых действий, которые пользователь взял. Сразу после создания ClassB добавьте наблюдателя в ClassA с правильным значением NSKeyValueObservingOption.

Если вы просто хотите, чтобы вас уведомляли, когда "имя" публичной собственности в ClassB изменяется, попробуйте следующее:

ClassB

@interface ClassB : UIViewController {
}

@property (retain) NSString* name;

- (void) aMethodThatModifiesName:(NSString*)newName;

@end


@implementation ClassB 

@synthesize name;

- (void) aMethodThatModifiesName:(NSString*)newName {
    // do some stuff
    self.name = newName;
}

@end

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