2008-10-03 3 views
13

Ich bin es gewohnt, Java Swing UIs zu kodieren, und in denen, wenn Sie einige Eigenschaften haben, die ändern, und Sie möchten Ihre UI aktualisieren würde das beobachtbare/beobachtbare Muster implementieren. In Java machst du das normalerweise, indem deine Klasse eine Liste von Listenern verwaltet, die von verschiedenen Ereignissen benachrichtigt werden.Was ist der beste Weg, Beobachter/Observable in Objective-c zu tun (iphone Version)

Ich habe mit Objective-C auf dem Mac gespielt, und das hat KVC und Bindung, die sehr gut funktioniert, und erfordert weniger Code. Das iPhone SDK scheint diese Funktionalität jedoch nicht zu haben, also lautet meine Frage: Wenn ich eine Klasse habe, die Daten enthält, die sich ändern, was ist der beste Weg für mich, eine UI-Komponente mit dieser Klasse zu registrieren, damit sie benachrichtigt werden kann von Änderungen in den Daten, die es anzeigen muss?

Antwort

37

Es gibt zwei integrierte Möglichkeiten zur Beobachtung in Cocoa: Schlüsselwertbeobachtung und Benachrichtigungen. In keinem System müssen Sie eine Sammlung von Beobachtern selbst pflegen oder benachrichtigen; Das Framework wird das für Sie erledigen.

Mit der Schlüsselwertbeobachtung (KVO) können Sie eine Eigenschaft eines Objekts beobachten - einschließlich einer Eigenschaft, die eine Auflistung darstellt - und über Änderungen an dieser Eigenschaft benachrichtigt werden. Sie müssen nur das Objekt -addObserver:forKeyPath:options:context: senden, das das Objekt, für das Sie Updates erhalten möchten, übergibt, den Schlüsselpfad der Eigenschaft (relativ zum Empfänger), für den Sie Updates erhalten möchten, und die Arten von Updates, die Sie erhalten möchten. (Es gibt ähnliche Methoden, die Sie verwenden können, wenn Sie eine Eigenschaft beobachten möchten, die eine Auflistung darstellt.)

Benachrichtigungen sind älter und schwerer. Sie registrieren sich mit einem NSNotificationCenter - in der Regel das Standard-Center - ein Objekt und Selektor-Paar, um eine Benachrichtigung zu geben, wenn ein Ereignis auftritt. Das Benachrichtigungsobjekt selbst kann beliebige Daten über seine userInfo-Eigenschaft enthalten. Sie können festlegen, dass alle Benachrichtigungen eines bestimmten Namens statt der für ein bestimmtes Objekt geltenden Benachrichtigungen beobachtet werden.

Welche sollten Sie in einem bestimmten Fall verwenden? Wenn Sie Änderungen an einer bestimmten Eigenschaft eines bestimmten Objekts vornehmen möchten, verwenden Sie im Allgemeinen die Schlüsselwertbeobachtung. Dafür wurde es entwickelt und es ist absichtlich leicht. (Neben anderen Verwendungen ist dies die Grundlage, auf der Cocoa Bindings basieren.) Wenn Sie sich für eine Statusänderung interessieren, die nicht durch eine Eigenschaft dargestellt wird, sind Benachrichtigungen sinnvoller.

Um beispielsweise synchron zu bleiben, wenn der Benutzer den Namen eines Modellobjekts ändert, würde ich KVO verwenden. Um zu wissen, wann ein gesamtes Objektdiagramm gespeichert wurde, würde ich Benachrichtigungen verwenden.

+4

Große Antwort - aber wie entfernen Sie mit dem KVO-Ansatz einen Beobachter, der sich bei vielen Objekten registriert hat? Ich dachte (fälschlicherweise), dass KVO Benachrichtigungen unter der Haube verwendet hat - aber ich denke nicht, dass es funktioniert. Nach der Verwendung von addObserver: X forKeyPath: ..., wenn Sie später versuchen: [[NSNotificationCenter defaultCenter] removeObserver: X] funktioniert das nicht? Es scheint zu implizieren, dass Sie eine separate Liste aller Objekte, die X beobachtet, behalten müssen, damit Sie die Beobachtung entfernen können. Oder fehlt mir etwas? – TimM

+0

@TimM: Sie würden die entsprechende Methode für das beobachtete Objekt aufrufen. Zum Beispiel: '[self removeObserver: theObserver fürKeyPath: @" someProperty "];' – FreeAsInBeer

+0

Neu in OS X 10.7 Lion und iOS 5.0 gibt es eine Methode -removeObserver: forKeyPath: context: an die Sie den gleichen Kontext übergeben können, den Sie wann übergeben haben Hinzufügen des Beobachters. Sie sollten das tun, wann immer es möglich ist, falls mehrere Objekte denselben Schlüsselpfad beobachten. –

0

Das ist im Allgemeinen nicht die Art, wie es gemacht wird. Werfen Sie einen Blick auf die Diskussion here, insbesondere den Link zur Apple-Dokumentation.

Wenn Sie es immer noch so machen wollen, wie Sie es sagen, ist es nicht besonders schwierig, etwas wie Bindungen "von Hand" zu implementieren. Sie erstellen einfach ein "bindendes" Objekt, das weiß, wie Sie Änderungen abonnieren können, und stellt eine Verbindung zu einer Eigenschaft einer Ansicht her.

Um tatsächlich zu antworten, wie es gemacht wird - normalerweise haben Sie ein Controller-Objekt, das den Zustand des Modells überwacht (etwa wie ein Observer) und das/die View-Objekt (e) nach Bedarf aktualisiert.

+0

Ich frage nur, was am besten ist und ein JAVA Beispiel geben. Ich bin nicht besonders beunruhigt, wenn der Objective-C-Weg völlig anders ist, ich will nur wissen, was es ist. – rustyshelf

+0

Verstanden. Ich habe meine Antwort bearbeitet, um klarer zu machen, worüber ich gesprochen habe. –

9

Ich fand auch, dass Sie tun können: für Änderungsereignisse

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleWhateverChange) name:@"whateverChange" object:nil]; 

Um sich anzumelden, und

[[NSNotificationCenter defaultCenter] postNotificationName:@"whateverChange" object:nil]; 

sie zu feuern.Ich könnte eine N00b sein, aber ich konnte einfach nicht den Beobachter für die Schlüsselpfad-Sache für mich arbeiten lassen.

Verwandte Themen