4 Stimmen

Sollten Beobachter benachrichtigt werden, wenn insertObject:in<Key>AtIndex: aufgerufen wird?

Ich habe ein Modell, das an einen Array-Controller gebunden ist. Ich muss in der Lage sein, das Modell direkt zu aktualisieren und haben Benachrichtigungen an den Array-Controller über die Aktualisierung gesendet. Bei meiner Suche habe ich festgestellt, dass ich dies durch die Verwendung von mutableArrayValueForKey: auf mein Modell und die Aktualisierung durch das zurückgegebene NSMutableArray.

Ich fand auch mehrere Verweise, die mich zu der Annahme verleiteten, dass ich das Modell auch aktualisieren und Benachrichtigungen senden könnte, wenn ich die KVC-konformen Getter und veränderbaren indizierten Accessoren implementieren und verwenden würde. In meinem Code implementierte ich

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

Aufruf von insertObject:in<Key>AtIndex: hat nicht dazu geführt, dass meine Beobachter benachrichtigt wurden. Der folgende Code ist das kleinste Stück, das mir einfiel, um zu testen, was ich zu tun versuchte.

#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;
}

Wenn ich diesen Code ausführe, erhalte ich die folgende Ausgabe:

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

Ich hatte erwartet, drei weitere Protokollmeldungen zu sehen, die besagen, dass theArray jetzt 2, 3 oder 4 Elemente hat. Ich dachte, der Aufruf von insertObject:inTheArrayAtIndex sollte dem obvserver mitteilen, dass sich theArray geändert hat, aber in meinem Code ist das nicht der Fall.

Bin ich verwirrt, wenn ich denke, dass insertObject:inTheArrayAtIndex sollte dazu führen, dass den Beobachtern eine Benachrichtigung übermittelt wird über theArray ? Oder habe ich bei meiner Implementierung etwas übersehen? Für jede Hilfe bin ich dankbar.

9voto

Peter Hosey Punkte 94684

Das liegt daran, dass Sie nicht sowohl die insert- als auch die remove-Methode implementiert haben.

"Was!", sagst du. "Das habe ich auch!"

Nein, nicht ganz. Fast, aber Sie haben ein Wort falsch verstanden: Es ist removeObjectFromTheArrayAtIndex: .

Nach dieser Korrektur führen alle sechs Änderungen zu Beobachterbenachrichtigungen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X