iPhone KVO между двумя классами - PullRequest
14 голосов
/ 10 ноября 2010

В моем приложении есть два класса: класс 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 Ответ

38 голосов
/ 11 ноября 2010

Вы можете наблюдать изменения в разных объектах / классах.Я думаю, что проблема в параметре параметров 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.

Если вы просто хотите получать уведомления при каждом изменении открытого свойства "name" в 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
...