2009-10-17 98 views
0

喜研究员iPhone开发者,iPhone键值观察报:观察员的UITableViewController

不登记我是一名经验丰富的软件工程师,但新来的iPhone平台。我已经成功实现了sub-classed视图控制器,并可以在视图控制器堆栈上推送和弹出父视图/子视图。但是,当在子视图控制器中编辑对象时,尝试更新视图控制器时遇到了麻烦。经过多次失败的实验之后,我发现了键值观察器API,这看起来像是完成这个任务的完美方式。然后我在主/父视图控制器中注册了一个观察者,并且在观察者中我打算重新加载视图。这个想法是,当在子视图控制器中编辑对象时,它将被触发。但是,我认为观察者没有被注册,因为我知道值正在编辑视图控制器中更新(我可以在调试器中看到它),但观察方法从未被调用。

请帮忙!

代码片段如下。

被观察对象。我相信这是键值兼容的,因为使用setvalue消息调用时设置的值(请参见下面的子视图控制器)。

X.h:

@interface X : NSObject <NSCoding> { 
    NSString *name; 
... 
@property (nonatomic, retain) NSString *name; 

X.m:

@implementation X 

@synthesize name; 
... 

主视图或者Controller.h:

@class X; 

@interface XViewController : UITableViewController { 
    X *x; 
... 

主视图Controller.m或者:

@implementation XViewController 

@synthesize x; 
... 
- (void)viewDidLoad { 
    ... 
    [self.x addObserver:self 
      forKeyPath: @"name" 
      options:  (NSKeyValueObservingOptionNew | 
          NSKeyValueObservingOptionOld) 
      context:nil]; 

    [super viewDidLoad]; 
} 
... 
- (void)observeValueForKeyPath:(NSString *)keyPath 
        ofObject:(id)object 
        change:(NSDictionary *)change 
        context:(void *)context 
{ 
    if ([keyPath isEqual:@"name"]) { 
     NSLog(@"Found change to X"); 
    [self.tableView reloadData]; 
    } 

    [super observeValueForKeyPath:keyPath 
      ofObject:object 
      change:change 
      context:context]; 
} 

子视图Controller.m或者:(此正确地设置在儿童视图控制器对象的值)

[self.x setValue:[[tempValues objectForKey:key] text] forKey:@"name"]; 

回答

0

你检查,如果你调用的addObserver之前实例化在viewDidLoad中()的x对象:forKeyPath:选项:上下文:?您的x对象必须已经分配/初始化。

一个小问题。由于上下文参数被声明为(void *),因此您应该传递NULL,而不是nil(空对象指针代表id 0,而NULL代表(void *)0;它们代表两个相同的事物0,但在Objective C中,您必须区分表示空类指针的nil,NULL和Nil)。

+0

谢谢您指出缺陷。我发现如果我将观察者放在子视图控制器实例变量property(!)上,我可以触发事件。也就是说,在上面的例子中,当编辑按钮被按下时,我这样做: 主视图Controller.m ... ChildViewController.x = self.x; [ChildViewController.x \t的addObserver:自 \t \t \t \t \t forKeyPath:\t @ “姓名” 选项:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) 上下文:NULL]; [[self navigationController] pushViewController:ChildViewController animated:YES]; ... – Scott 2009-10-23 01:29:52

0

尽管在您的应用程序中可以使用关键值观察功能,但使用通知中心可能更适合“主要”视图控制器之间的通信。 (一个“主要”视图控制器是iPhone的全屏视图的主要控制器。)

这确保了两个视图控制器在通信发生时仍然存在。在我看来,KVO设计用于一个共同的环境 - 一个视图控制器或模型。

X类似乎符合KVC。虽然你不显示你是否在你的代码中声明了@property。我会假设你是这样做的。

你为什么这样做:

[self.X的setValue:[tempValues objectForKey:键]文] forKey:@ “名”];

在你的孩子视图控制器,而不是:

self.name = [[tempValues objectForKey:键]文]。

(和你真的是上述self.X self.X不self.x.?)

一个其他说明:你不需要打电话给你的超 - [observeValueForKeyPath:ofObject:变化:context:]方法。

Andrew

+0

谢谢你指出我不需要调用超类。一旦我发现事件发生,那就是例外。但是,代码self.x.name = [[temp ..和[self.x setValue:...实际上在功能上是等效的(我测试了这两个)。我不确定一个人是否比另一个人更有效率,但是感谢你让我看到另一个选择。我对KVO文档的阅读使我认为我需要[self.x setValue ...语法。 – Scott 2009-10-23 01:36:09