两个类之间的iPhone KVO

fmc*_*ley 14 iphone key-value-observing ios

我的应用程序类A和类B中有两个类.A类和B类都是UIViewController的实例.A类有一个按钮,推送时将B类推入堆栈.B类有一个A类想要观察的字符串,并根据需要更新它的接口.我已经能够使用: [self addObserver:self forKeyPath:@"name" options:0 context:NULL];在B类中查看对字符串的更改.当我尝试在A类viewWillAppear方法中使用以下内容时:

ClassB *b = [[ClassB alloc]init];
[b addObserver:self forKeyPath:@"name" options:0 context:NULL];
Run Code Online (Sandbox Code Playgroud)

并添加方法:

(void)observeValueForKeyPath:(NSString )keyPath ofObject:(id)object
                      change:(NSDictionary )change
                     context:(void )context
Run Code Online (Sandbox Code Playgroud)

尝试从A中查看B中所做的更新时没有触发任何操作.我觉得这个问题很傻但是KVO如何在iOS中的两个类之间工作?我知道这应该有效.

nek*_*kno 38

您可以观察不同对象/类的变化.我认为问题出在选项参数中addObserver:forKeyPath:options:context:.

您想要做的观察类型有多种选择.该志愿指南是一个很好的起点,但你可能想NSKeyValueObservingOptionNew,我在下面的例子中使用.

首先,"名称"应该是ClassB中的公共财产.

其次,您可能不需要viewWillAppear在ClassA 中将观察者添加到"b"中,因为每次出现ClassA视图时都不需要添加它.在创建ClassB视图时,您只需要添加一次观察者.一旦添加了观察者,该observeValueForKeyPath:ofObject:change:context:方法将在ClassA中执行,因此您可以从那里对ClassA UI进行更新.每次ClassA即将出现时,您都不需要做任何事情.

在A类中,您可能应该在将ClassB推送到控制器堆栈之前创建ClassB,可能是在用户采取某些操作的事件处理程序中.创建ClassB后,立即在ClassA中添加具有正确NSKeyValueObservingOption值的观察者.

如果您只是希望在ClassB中的公共属性"name"发生更改时收到通知,请尝试以下操作:

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

  • 如果这有助于任何人,我遇到的问题是我的observeValueForKeyPath消息没有被触发,即使我写出来与nekno几乎完全一样.你*有*使用self.name = newvalue,*NOT*just name = newvalue来更改属性. (6认同)