我的应用程序类A和类B中有两个类.A类和B类都是UIViewController的实例。 A类有一个按钮,推送时将B类推入堆栈。 B类有一个A类想要观察的字符串,并根据需要更新它的接口。我已经能够使用:
B类中的[self addObserver:self forKeyPath:@"name" options:0 context:NULL];
用于查看字符串的更改。
当我尝试在A类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
尝试从A中查看B中所做的更新时,没有触发任何操作。我觉得这个问题很傻,但KVO在iOS中的两个类之间如何工作?我知道这应该有用。
答案 0 :(得分:38)
您可以观察不同对象/类的变化。我认为问题出在addObserver:forKeyPath:options:context:
的选项参数中。
您想要做的观察类型有多种选择。 KVO Guide是一个很好的起点,但您可能需要NSKeyValueObservingOptionNew
,我在下面的示例中使用了viewWillAppear
。
首先,“name”应该是ClassB中的公共属性。
其次,您可能不需要在ClassA中的observeValueForKeyPath:ofObject:change:context:
中将观察者添加到“b”,因为每次出现ClassA视图时都不需要添加它。在创建ClassB视图时,您只需要添加一次观察者。添加观察者后,{A}}方法将在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
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