2009-10-17 109 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