Wenn Sie jemals mit KVO (Key-Value Observing) in Cocoa gearbeitet haben, sind die Chancen groß, dass Sie auf verschiedene Arten von Problemen stoßen. Die API ist nicht großartig. Wenn Sie vergessen, einen Beobachter zu entfernen, kann dies zu Speicherverlusten oder sogar noch schlimmeren Abstürzen führen. Die KVOController-Bibliothek von Facebook soll dieses Problem lösen.
Wenn Sie das Key-Value-Observing oder KVO noch nicht kennen, sollten Sie zunächst das Entwicklerhandbuch von Apple zu diesem Thema oder den Artikel von Mattt Thompson über NSHipster lesen. Um das Handbuch von KVO zu KVO zu zitieren: "Die Beobachtung von Schlüsselwerten bietet einen Mechanismus, mit dem Objekte über Änderungen an bestimmten Eigenschaften anderer Objekte benachrichtigt werden können." Mattt definiert KVO wie folgt: "Das Beobachten von Schlüsselwerten ermöglicht eine Ad-hoc-Ereignisprüfung zwischen bestimmten Objektinstanzen, indem auf Änderungen an einem bestimmten Schlüsselpfad gewartet wird." Die Schlüsselwörter sind ereignet sich und Schlüsselpfad.
Bevor wir die KVOController-Bibliothek besprechen, möchte ich mich kurz mit der KVO-API beschäftigen.
Ich werde KVO in diesem Tutorial nicht ausführlich behandeln, aber es ist wichtig, dass Sie das Kernkonzept von KVO verstehen. Die Idee ist einfach. Ein Objekt kann Änderungen an bestimmten Eigenschaften eines anderen Objekts überwachen. Das Beobachtungsobjekt wird vom Zielobjekt als Beobachter für einen bestimmten Schlüsselpfad hinzugefügt.
Lassen Sie uns dies an einem Beispiel veranschaulichen. Ob objectB
möchte informiert werden, wenn die Name
Eigentum von objectA
ändert sich dann objectA
muss hinzufügen objectB
als Beobachter für den Schlüsselpfad Name
. Dank der Ausführlichkeit von Objective-C ist der Code dafür ziemlich einfach.
[objectA addObserver: objectB forKeyPath: @ "name" -Optionen: NSKeyValueObservingOption Neuer Kontext: NULL];
Wann auch immer objectA
's Name
Eigenschaft ändert sich, observValueForKeyPath: ofObject: change: context:
wird aufgerufen. Der erste Parameter ist der Schlüsselpfad, der von beobachtet wird objectB
, Der zweite Parameter ist das Objekt des Schlüsselpfads, das dritte Argument ist ein Wörterbuch, in dem die Änderungen beschrieben werden, und das letzte Argument ist der Kontext, der als letztes Argument von übergeben wurde addObserver: forKeyPath: Optionen: Kontext:
.
Ich hoffe, Sie stimmen zu, dass dies nicht sehr elegant ist. Wenn Sie KVO umfassend einsetzen, wird die Implementierung von observValueForKeyPath: ofObject: change: context: schnell lang und komplex.
Es ist wichtig, nicht länger auf Änderungen zu achten, wenn ein Objekt nicht mehr an Benachrichtigungen für einen bestimmten Schlüsselpfad interessiert ist. Dies geschieht durch Aufruf removeObserver: forKeyPath:
oder removeObserver: forKeyPath: Kontext:
.
Das Problem, mit dem jeder Entwickler zu einem bestimmten Zeitpunkt konfrontiert ist, hat entweder den Anruf vergessen removeObserver: forKeyPath:
oder anrufen removeObserver: forKeyPath:
mit einem Schlüsselpfad, der vom Beobachter nicht beobachtet wird. Die Gründe dafür sind vielfältig und die Ursache für das Problem, mit dem viele Entwickler bei der Arbeit mit KVO konfrontiert sind.
Wenn du vergisst zu rufen removeObserver: forKeyPath:
, Sie könnten mit einem Speicherleck enden. Wenn du anrufst removeObserver: forKeyPath:
und das Objekt ist nicht als Beobachter registriert, es wird eine Ausnahme ausgelöst. Die Kirsche auf dem Kuchen ist das NSKeyValueObserving
Das Protokoll bietet keine Möglichkeit, zu überprüfen, ob ein Objekt einen bestimmten Schlüsselpfad beobachtet.
Glücklicherweise ärgerte das Cocoa-Team bei Facebook die oben genannten Probleme ebenso wie Sie und sie hatten eine Lösung, die KVOController-Bibliothek. Anstatt das Rad neu zu erfinden, entschied sich das Team von Facebook, auf KVO aufzubauen. Trotz seiner Unzulänglichkeiten ist KVO robust, breit unterstützt und sehr nützlich.
Die KVOController-Bibliothek fügt KVO einige Dinge hinzu:
Bevor wir beginnen, muss betont werden, dass für die KVOController-Bibliothek ARC erforderlich ist und die Mindestimplementierungsziele iOS 6 für iOS und 10.7 für OS X sind.
Ich bin ein großer Befürworter von CocoaPods und ich hoffe, dass Sie es auch sind. Um die KVOController-Bibliothek mit CocoaPods zu einem Projekt hinzuzufügen, fügen Sie den Pod zur Pod-Datei Ihres Projekts hinzu und führen Sie ihn aus Pod-Update
um die Bibliothek zu installieren.
pod 'KVOController'
Alternativ können Sie die neueste Version der Bibliothek von GitHub herunterladen und die Bibliothek durch Kopieren manuell hinzufügen KVOController.h und KVOController.m zu deinem Projekt.
Das erste, was Sie tun müssen, ist das Initialisieren einer Instanz von FBKVOController
Klasse. Werfen Sie einen Blick auf das folgende Code-Snippet, in dem ich ein FBKVOController
Instanz in einem View-Controller initWithNibName: Bundle:
Methode.
- (id) initWithNibName: (NSString *) nibNameOrNil-Bundle: (NSBundle *) nibBundleOrNil self = [super initWithNibName: nibNameOrNil-Bundle: nibBundleOrNil]; if (self) _KVOController = [FBKVOController controllerWithObserver: self]; return self;
Beachten Sie, dass ich einen Verweis auf die speichere FBKVOController
Objekt im View Controller _KVOController
Instanzvariable. Eine großartige Funktion der KVOController-Bibliothek besteht darin, dass der Beobachter in dem Moment automatisch entfernt wird, in dem er installiert wird FBKVOController
Objekt wird freigegeben. Mit anderen Worten, es ist nicht notwendig, den Beobachter zu entfernen, da dies automatisch in dem Moment erfolgt, in dem der Beobachter das Ziel erreicht FBKVOController
Objekt wird freigegeben.
Sie haben mehrere Möglichkeiten, ein Objekt zu beobachten. Sie können den traditionellen Ansatz verwenden, indem Sie aufrufen Beachten Sie: keyPath: Optionen: Kontext:
. Das Ergebnis ist das observValueForKeyPath: ofObject: change: context:
wird aufgerufen, wenn ein Änderungsereignis stattfindet.
[_KVOController muss Folgendes beachtet werden: person keyPath: @ "name" -Optionen: NSKeyValueObservingOptionNew context: NULL];
Jedoch die FBKVOController
class verwendet auch Blöcke und benutzerdefinierte Aktionen, wie Sie in den folgenden Codeausschnitten sehen können. Ich bin sicher, Sie stimmen zu, dass dies die Arbeit mit KVO viel angenehmer macht.
[_KVOController observ: person keyPath: @ "name" -Optionen: NSKeyValueObservingOptionNew Block: ^ (ID-Beobachter, ID-Objekt, NSDictionary * change) // Antworten auf Änderungen];
[_KVOController muss Folgendes beachtet werden: person keyPath: @ "name" -Optionen: NSKeyValueObservingOptionNew-Aktion: @selector (nameDidChange :)];
Obwohl der Betrachter automatisch entfernt wird, wenn der FBKVOController
Objekt wird freigegeben, es ist oft notwendig, die Beobachtung eines Objekts zu beenden, bevor der Beobachter freigegeben wird. Die KVOController-Bibliothek verfügt über eine Reihe von Methoden, um diese einfache Aufgabe auszuführen.
Um die Beobachtung eines bestimmten Schlüsselpfads eines Objekts zu beenden, rufen Sie auf unobserve: keyPath:
und übergeben Sie den Objekt- und Schlüsselpfad. Sie können die Beobachtung eines Objekts auch durch Aufrufen beenden nicht beobachten:
und übergeben Sie das Objekt, das Sie nicht mehr beobachten möchten. Um die Beobachtung jedes Objekts zu beenden, können Sie das senden FBKVOController
eine Nachricht von unobserveAll
.
Wenn Sie einen Blick auf die Implementierung der FBKVOController
Klasse, werden Sie feststellen, dass eine interne Karte der Objekte und Schlüsselpfade vorhanden ist, die der Beobachter beobachtet. Das FBKVOController
Klasse ist verzeihender als die KVO-Implementierung von Apple. Wenn du das sagst FBKVOController
object, um die Beobachtung eines Objekts oder Schlüsselpfads zu stoppen, das nicht beobachtet wird, es wird keine Ausnahme ausgelöst. Das ist wie es sein sollte.
Auch wenn KVO kein schwer zu verstehendes Konzept ist, ist sicherzustellen, dass die Beobachter ordnungsgemäß entfernt werden und die Rennbedingungen nicht zu einem Chaos führen, wenn man mit KVO arbeitet.
Ich empfehle Ihnen, sich die KVOController-Bibliothek anzuschauen. Ich empfehle Ihnen jedoch auch, sich mit KVO vertraut zu machen, bevor Sie es in Ihren Projekten einsetzen, damit Sie wissen, was diese Bibliothek hinter den Kulissen für Sie tut.