2009-07-09 15 views
19

Ist es möglich, Änderungen an Werten zu beobachten, die unter verschiedenen Schlüsseln in einem NSMutableDictionary gespeichert sind? In meinem Fall würden die Schlüssel bereits existieren, wenn das Abonnement initiiert wird, aber die Werte ändern sich und ich möchte in diesem Fall benachrichtigt werden. Ich möchte den Schlüssel des geänderten Wertes in der Benachrichtigung haben.Beobachten von NSMutableDictionary-Änderungen

Ich nehme an, dass, wenn meine Wörterbuchschlüssel alle NSString-Instanzen wären, ich einfach jeden Schlüsselpfad einzeln abonnieren könnte. Aber was, wenn meine Schlüssel keine Zeichenfolgen sind? Habe ich in diesem Fall kein Glück?

Antwort

6

Das ist eine interessante Idee. Ich kann nichts in NSDictionary oder NSDictionaryController finden, das vielversprechend aussieht. Mein erster Instinkt wäre die Verwendung von Kompositionen um ein NSMutableDictionary und das Abfangen von Aufrufen von setObject: forKey: (und vielleicht -removeObjectForKey :), um Abonnenten über Änderungen zu informieren.

Es gibt eine Cocoa With Love post auf Unterklasse NSMutableDictionary, die wahrscheinlich nützlich sein wird, sollten Sie diese Route gehen. Ich habe auch created my own NSMutableDictionary subclasses, und Sie können gerne den Open-Source-Code verwenden.

Sie könnten ein Beobachterprotokoll entwerfen, das bestimmte Schlüssel angibt, die überwacht werden sollen. Sollte nicht zu viel Code sein, aber mehr als ich im Moment Zeit habe, um zu werfen.

+0

Danke. Ich denke, Zusammensetzung um ein NSMutableDictionary ist der Weg zu gehen. Ich kann immer noch nicht sehen, wie man das macht, wenn die Schlüssel NSStrings sind, aber ich denke, dass ich damit arbeiten kann. –

+0

@Quinn Taylor: Der Link zu Ihrer benutzerdefinierten Unterklasse scheint tot und ich müsste diesen Code überprüfen. Hast du es noch irgendwo herumhängen? – Cyrille

6

Ich habe dies jetzt erfolgreich implementiert, mit der Zusammensetzung um das NSMutableDictionary. Ich bin überrascht, wie wenig Code es brauchte. Die Klasse, die ich implementiert habe, ist Board, das zur Darstellung des Modells in einem Brettspiel verwendet wird. Jeder kann durch den Aufruf der addObserver Änderungen für Board Staaten abonnieren: Verfahren, wie dies umgesetzt:

- (void)addObserver:(id)observer { 
    for (id key in grid) 
     [self addObserver:observer 
       forKeyPath:[key description] 
        options:0 
        context:key]; 
} 

Da Sie nur auf die Tasten mit der KVO Modell abonnieren können, ich betrogen und auf die Beschreibung abonniert des Schlüssels , aber den Schlüssel selbst als Kontext übergeben. In Objekten, die Instanzen meines Board beobachten, implementiere ich -observeValueForKeyPath:ofObject:change:context:, um die keyPath-Zeichenfolge zu ignorieren und nur den übergebenen Kontext zu verwenden.

Meine einfache Brett Klasse ist nicht KVO-konform für die künstlichen Eigenschaften ich diese Methode create verwenden, so dass ich bestehen 0 in der options Eigenschaft so die KVO Maschinen werden nicht versuchen, die alten/neuen Werte dieses Schlüssels. Das würde meinen Code sprengen.

Alles, was das Board ändert (in meiner einfachen Klasse gibt es nur eine Methode, die dies der Fall ist) die erforderlichen Meldungen erhöhen die KVO Maschinen zu veranlassen, in Aktion zu springen:

- (void)setPiece:(id)piece atLocation:(Location*)loc { 
    [self willChangeValueForKey:[loc description]]; 
    [grid setObject:piece forKey:loc]; 
    [self didChangeValueForKey:[loc description]]; 
} 

Voila! Abonnement für ein NSMutableDictionary mit Nicht-Stringschlüsseln!

+0

Abonnieren der Beschreibung ist ein netter Trick! –