2011-02-05 3 views
4

私はモデルをアレイコントローラに接続しています。モデルを直接更新して、アレイコントローラにアップデートに関する通知を送信する必要があります。私の検索では、mutableArrayValueForKey:を私のモデルに使い、返されたNSMutableArrayを更新することでこれを達成できることを発見しました。insertObject:<Key>のAtIndex:が呼び出されたときにオブザーバに通知する必要がありますか?

また、KVC準拠のゲッターと可変インデックス付きアクセサを実装して使用すると、モデルを更新して通知を受け取ることができると私は考えました。私のコードで実装しました

-countOf<Key>: 
-objectIn<Key>AtIndex: 
-insertObject:in<Key>AtIndex: 
-removeObjectFrom<Key>AtIndex: 

insertObject:in<Key>AtIndex:を呼び出すと、私のオブザーバーに通知されませんでした。以下のコードは、私がしようとしていることをテストするために思いつくことができる最小のものです。

#import <Foundation/Foundation.h> 

@interface ModelAndObserver : NSObject { 
    NSMutableArray *theArray; 
} 

@property(retain)NSMutableArray *theArray; 

- (NSUInteger)countOfTheArray; 
- (NSString *)objectInTheArrayAtIndex:(NSUInteger)index; 
- (void)insertObject:(NSString*) string inTheArrayAtIndex:(NSUInteger)index; 
- (void)removeObjectInTheArrayAtIndex:(NSUInteger)index; 
@end 

@implementation ModelAndObserver 
@synthesize theArray; 

- (void)observeValueForKeyPath:(NSString *)keyPath 
         ofObject:(id)object 
         change:(NSDictionary *)change 
         context:(void *)context 
{ 
    NSLog(@"theArray now has %d items", [theArray count]); 
} 

- (NSUInteger)countOfTheArray 
{ 
    return [theArray count]; 
} 

- (NSString *)objectInTheArrayAtIndex:(NSUInteger)index 
{ 
    return [theArray objectAtIndex:index]; 
} 

- (void)insertObject:(NSString*) string inTheArrayAtIndex:(NSUInteger)index 
{ 
    [theArray insertObject:string atIndex:index]; 
} 

- (void)removeObjectInTheArrayAtIndex:(NSUInteger)index 
{ 
    [theArray removeObjectAtIndex:index]; 
} 

@end 


int main (int argc, const char * argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    ModelAndObserver *mao = [[ModelAndObserver alloc] init]; 

    [mao addObserver:mao 
     forKeyPath:@"theArray" 
      options:0 
      context:@"arrayChanged"]; 

    // This results in observeValueForKeyPath... begin called. 
    [mao setTheArray:[NSMutableArray array]]; 

    // This results in observeValueForKeyPath... begin called. 
    [[mao mutableArrayValueForKey:@"theArray"] addObject:@"Zero"]; 

    // These do not results in observeValueForKeyPath... 
    // begin called, but theArray is changed. 
    [mao insertObject:@"One" inTheArrayAtIndex:1]; 
    [mao insertObject:@"Two" inTheArrayAtIndex:2]; 
    [mao insertObject:@"Three" inTheArrayAtIndex:3]; 

    // This results in observeValueForKeyPath... begin called. 
    [[mao mutableArrayValueForKey:@"theArray"] addObject:@"Four"]; 


    [mao removeObserver:mao forKeyPath:@"theArray"]; 
    [mao release]; 
    [pool drain]; 
    return 0; 
} 

私は次の出力を取得し、このコードを実行すると:私はtheArrayは今、2、3、または4のアイテムを持っていると言う3つのログメッセージを確認するために期待していた

 
2011-02-05 17:38:47.724 kvcExperiment[39048:a0f] theArray now has 0 items 
2011-02-05 17:38:47.726 kvcExperiment[39048:a0f] theArray now has 1 items 
2011-02-05 17:38:47.727 kvcExperiment[39048:a0f] theArray now has 5 items 

を。私は、呼び出しがinsertObject:inTheArrayAtIndexは、theArrayが変更されたことをobvserverに通知しておくべきだと思ったが、私のコードではそうではない。

insertObject:inTheArrayAtIndexは、オブザーバーにtheArrayという通知が送信されるはずですか?あるいは、私の実装で何か迷っていましたか?どんな助けもありがとうございます。

答えて

9

これは、挿入メソッドと削除メソッドの両方を実装していないためです。

「なんと! 「私もやった!」

いいえ、それほどではありません。ほとんどですが、間違った言葉があります:removeObjectFromTheArrayAtIndex:です。

この修正を適用すると、6つの変更がすべてオブザーバー通知を引き起こします。

関連する問題