KVO-Benachrichtigungen für eine Änderung eines NSArray, das von einem NSMutableArray unterstützt wird

7

Ich versuche KVO zu verwenden, um Sammlungsänderungsereignisse in einer NSArray-Eigenschaft anzuhören. Öffentlich ist die Eigenschaft ein schreibgeschütztes NSArray, wird jedoch von einem NSMutableArray-Steuerelement unterstützt, sodass ich die Auflistung ändern kann.

Ich weiß, dass ich die Eigenschaft auf einen neuen Wert setzen kann, um eine "set" -Änderung zu erhalten, aber ich bin daran interessiert, Änderungen hinzuzufügen, zu entfernen oder zu ersetzen. Wie melde ich diese Art von Änderungen für ein NSArray richtig?

%Vor%

%Vor%

Beobachterklasse:

%Vor%     
Kevin DiTraglia 06.06.2014, 19:05
quelle

1 Antwort

18

Zuerst sollten Sie verstehen, dass KVO zum Beobachten eines Objekts für Änderungen seiner Eigenschaften dient. Das heißt, Sie können ein Array nicht als solches beobachten. Sie beobachten eine indizierte Sammlungseigenschaft. Diese Eigenschaft kann von einem Array unterstützt oder auf andere Weise implementiert werden. Solange es KVC-konform ist und KVO-konform modifiziert wurde, reicht das. (Es spielt also keine Rolle, ob die Eigenschaft vom Typ NSArray* ist oder mit NSMutableArray* oder irgendetwas implementiert wurde.)

Sie beobachten also eine Instanz von Model für Änderungen in der Eigenschaft items . Wenn Sie möchten, dass der Beobachter eine Änderungsbenachrichtigung erhält, müssen Sie sicherstellen, dass Sie die items -Eigenschaft immer KVO-konform ändern.

Der beste Weg, meiner Meinung nach, ist die Umsetzung der veränderbare indizierte Sammlungsaccessoren und diese immer verwenden, um die Eigenschaft zu ändern. Also würden Sie mindestens eines davon implementieren:

%Vor%

Und eins davon:

%Vor%

Wenn die Eigenschaft von einem NSMutableArray unterstützt wird, sind die obigen Methoden einfache Wrapper um die entsprechenden Methoden in _items .

Jede andere Methode, die Sie schreiben, um Ihre Eigenschaft zu ändern, sollte eine davon durchlaufen. Also wäre Ihre -addItem: -Methode:

%Vor%

Sie können auch den einfachen Getter für die items -Eigenschaft entfernen und stattdessen nur die indizierten Sammlungs-Getter verfügbar machen:

%Vor%

Das ist jedoch nicht notwendig, wenn es einen typischen Getter gibt.

(Die Existenz dieser Accessoren ermöglicht es Ihnen, eine to-many-Eigenschaft zu implementieren, die nicht vom Typ NSArray ist. Aus Sicht von KVC ist keine tatsächliche Array-typisierte Schnittstelle erforderlich.) p>

Ich persönlich empfehle das nicht, aber sobald Sie solche Accessoren haben, können Sie die Eigenschaft auch mutieren, indem Sie den NSMutableArray -ähnlichen Proxy für die Eigenschaft mit -mutableArrayValueForKey: erhalten und dann Mutationsoperationen an sie senden. In diesem Fall könnten Sie [[self mutableArrayValueForKey:@"items"] addObject:item] verwenden. Ich mag das nicht, weil ich der Meinung bin, dass die Schlüsselwertcodierung für den Schlüssel der Daten ist. Es ist dynamisch oder in einer Datendatei wie eine NIB gespeichert, nicht zur Kompilierzeit bekannt. Fest codierte Schlüsselnamen, wenn Sie die Möglichkeit haben, ein Sprachsymbol (z. B. Selektor) zu verwenden, um die Eigenschaft zu adressieren, ist ein Code-Geruch.

Es kann jedoch gerechtfertigt sein, dass Vorgänge, die in Bezug auf die indizierten Zugriffsmethoden wirklich umständlich sind, wie zum Beispiel das Sortieren, durchgeführt werden.

Schließlich können Sie die NSKeyValueObserving verwenden. Die Methoden -willChange... und -didChange... des Protokolls protokollieren Änderungsmeldungen, wenn Sie den Sicherungsspeicher der Eigenschaft direkt ändern, ohne eine Mutationsmethode zu durchlaufen, die KVO erkennt und einliest. Für eine indizierte Sammlungseigenschaft wären das die Methoden -willChange:valuesAtIndexes:forKey: und -didChange:valuesAtIndexes:forKey: . Das ist ein noch schlimmerer Code-Geruch, soweit es mich betrifft.

    
Ken Thomases 06.06.2014, 20:53
quelle