Was ist der beste Weg, um zwischen View-Controllern zu kommunizieren?
Wird neu in objective-c, cocoa und dem iPhone dev im Allgemeinen, ich habe einen starken Wunsch, um das beste aus der Sprache und der frameworks.
Einer der Ressourcen, die ich verwende, ist Stanford CS193P Klasse Notizen, die Sie verlassen haben auf das web. Es besteht aus einer Vorlesung Notizen, Aufgaben und Beispiel-code, und da der Kurs wurde von Apple die dev ' s, die ich auf jeden Fall überlegen, es zu werden "aus dem Maul des Pferdes".
Klasse Website:
http://www.stanford.edu/class/cs193p/cgi-bin/index.php
Vorlesung 08 ist mit einer Zuweisung zu bauen, ein UINavigationController-basierte app, die mehrere UIViewControllers drückte auf den UINavigationController-stack. Das ist, wie der UINavigationController funktioniert. Das ist logisch. Es gibt jedoch einige stern Warnungen in der Folie über die Kommunikation zwischen Ihrem UIViewControllers.
Werde ich zitiere aus diesem ernst der Folien:
http://cs193p.stanford.edu/downloads/08-NavigationTabBarControllers.pdf
Seite 16/51:
Wie Nicht Zu Teilen Daten
- Globale Variablen oder singletons
- Dies beinhaltet Ihre Anwendung delegieren
- Direkte Abhängigkeiten machen Ihr code weniger wiederverwendbar
- Und schwieriger zu Debuggen & test
Ok. Ich bin down mit. Nicht blind werfen alle Ihre Methoden, die verwendet werden wird für die Kommunikation zwischen den viewcontroller in Ihre app zu delegieren und auf die viewcontroller-Instanzen in der app-delegate-Methoden. Fair 'nuff.
Etwas weiter auf, wir Holen diese Folie sagt uns, was wir sollte tun.
Seite 18/51:
Best Practices für den Fluss der Daten
- Herauszufinden, genauwas vermittelt werden sollte,
- Definieren von input-Parametern für Ihre view-controller
- Für die Kommunikation zurück auf die Hierarchie, verwenden Sie lose Kopplung
- Definieren Sie eine generische Schnittstelle für Beobachter (wie delegation)
Diese Folie wird dann gefolgt von, was scheint, ein Platz Halter schieben, wo der Dozent dann offenbar zeigt die best practices an einem Beispiel mit der UIImagePickerController. Ich wünschte die videos waren verfügbar! 🙁
Ok, also... ich fürchte, mein objc-fu ist nicht so stark. Ich bin auch ein bisschen verwirrt durch die Letzte Zeile im obigen Zitat. Ich habe seit meinen Gerechten Anteil googeln über dies und ich habe gefunden, was erscheint, um eine menschenwürdige Artikel spricht über die verschiedenen Methoden der Beobachtung/Anzeige Techniken:
http://cocoawithlove.com/2008/06/five-approaches-to-listening-observing.html
Methode #5 auch zeigt Delegierten als eine Methode! Außer.... Objekte können nur einen Delegierten zu einer Zeit. Also, wenn ich mehrere viewcontroller Kommunikation, was soll ich tun?
Ok, das ist das set-up in gang. Ich weiß, ich kann einfach nicht meine Kommunikation Methoden in der app delegieren, die durch Verweis die mehrere viewcontroller-Instanzen in meiner appdelegate, aber ich wollen, das zu tun diese Art der Sache die Recht Weg.
Bitte helfen Sie mir "do the right thing" durch die Beantwortung der folgenden Fragen:
- Wenn ich versuche, schieben Sie einen neuen viewcontroller auf der UINavigationController-stack, wer werden sollte, dies zu tun zu schieben. Die Klasse/Datei in meinem code ist der richtige Ort?
- Wenn ich will, um zu beeinflussen, ein Stück von Daten (Wert eines iVar) in einem meiner UIViewControllers, wenn ich in einem verschiedenen UIViewController, was ist die "richtige" Art und Weise, dies zu tun?
- Geben, wir können nur einen Delegierten setzen in einer Zeit, in der ein Objekt, wie würde die Umsetzung Aussehen, wenn der Dozent sagt "Definieren Sie eine generische Schnittstelle für Beobachter (wie delegation)". Ein pseudocode Beispiel wäre furchtbar hilfreich ist hier, wenn möglich.
InformationsquelleAutor der Frage | 2009-02-20
Du musst angemeldet sein, um einen Kommentar abzugeben.
Diese sind gute Fragen, und seine große, um zu sehen, Sie tun Forschung und scheinen befasst sich mit lernen, wie man "es richtig machen" statt nur hacken zusammen.
Erstenich Stimme mit den vorherigen Antworten, die den Fokus auf die Bedeutung von Daten in model-Objekte bei entsprechenden (gemäß dem MVC-Entwurfsmuster). In der Regel will man vermeiden, dass Staatliche Informationen in einem controller, es sei denn, es ist streng "Präsentation" Daten.
Zweitensiehe Seite 10 der Stanford-Präsentation für ein Beispiel, wie programmgesteuert push ein controller auf dem Navigations-controller. Für ein Beispiel, wie das "optisch" mit Interface Builder, werfen Sie einen Blick auf dieses tutorial.
Drittenund vielleicht am wichtigsten ist, beachten Sie, dass die "best practices" erwähnt, die in der Stanford-Präsentation sind viel einfacher zu verstehen, wenn Sie darüber nachdenken, Sie in den Kontext der "dependency injection" design pattern". Kurz gesagt, bedeutet dies, dass der controller sollte nicht "look up" der Objekte, die es braucht, um seine Arbeit zu tun (z.B., verweisen auf eine Globale variable). Stattdessen sollten Sie immer auf "inject" diese Abhängigkeiten in den controller (also, pass in die Objekte, die es braucht, über Methoden).
Wenn Sie Folgen Sie den dependency-injection-Muster, wird der controller modular und wiederverwendbar. Und wenn Sie darüber nachdenken, wo die Stanford Moderatoren kommen (d.h., als Apple-Mitarbeiter Ihren job zu bauen Klassen, die können leicht wiederverwendet werden), Wiederverwendbarkeit und Modularität sind hohe Prioritäten. Alle der besten Methoden, die Sie erwähnen, für den Austausch von Daten sind Teil der dependency injection.
Das ist der Kern meiner Antwort. Ich werde auch ein Beispiel für die Verwendung der dependency injection-Muster mit einem controller unten im Gehäuse ist es hilfreich.
Beispiel für die Verwendung von Dependency Injection mit einem View-Controller
Sagen wir mal, du baust einen Bildschirm, in dem mehrere Bücher aufgelistet sind. Der Benutzer kann wählen Bücher, die er/Sie kaufen möchte, und Tippen Sie dann auf den button "zur Kasse" zu gehen, um den checkout-Bildschirm.
Zu bauen, erstellen Sie einen BookPickerViewController Klasse, die Steuerung und zeigt die GUI/view-Objekte. Wo wird es das ganze Buch Daten? Lassen Sie uns sagen, es hängt von einem BookWarehouse Objekt. So, jetzt Ihr-controller ist im Grunde der Vermittlung von Daten zwischen einem model-Objekt (BookWarehouse) und die GUI/view-Objekte. In anderen Worten, BookPickerViewController HÄNGT von der BookWarehouse Objekt.
Nicht tun:
Statt, die Abhängigkeiten eingefügt werden soll wie dieses:
Wenn die Apple-Jungs sprechen über die Verwendung der delegation pattern "kommunizieren zurück auf die Hierarchie," Sie reden immer noch über dependency injection. In diesem Beispiel, was soll der BookPickerViewController tun, wenn die Benutzer gepflückt hat, seine/Ihre Bücher und ist bereit, heraus zu überprüfen? Gut, das ist nicht wirklich Ihr job. Es sollten DELEGIEREN, dass die Arbeit an ein anderes Objekt, was bedeutet, dass es HÄNGT davon ab, auf ein anderes Objekt. So könnten wir ändern unsere BookPickerViewController init-Methode wie folgt:
Das Ergebnis von all diesem ist, dass Sie können geben Sie mir Ihre BookPickerViewController Klasse (und der zugehörigen GUI/view-Objekte) und ich kann es problemlos verwenden, in meiner eigenen Anwendung, vorausgesetzt, BookWarehouse und CheckoutController sind generische Schnittstellen (d.h., Protokolle), die ich umsetzen kann:
Schließlich nicht nur, dass Ihre BookPickerController wiederverwendbare aber auch einfacher zu testen.
InformationsquelleAutor der Antwort Clint Harris
Diese Art der Sache ist immer eine Frage des Geschmacks.
Gesagt, dass ich immer lieber zu meinem Koordination (#2) über model-Objekte. Die top-level-view-controller geladen oder erstellt die Modelle, die es braucht, und jedes view-controller stellt Eigenschaften in seiner untergeordneten Steuerungen, um Ihnen zu sagen, welche Modell Objekte, die Sie benötigen, um mit zu arbeiten. Die meisten Veränderungen werden zurück auf die Hierarchie durch die Verwendung von NSNotificationCenter; die Entlassung der Meldungen ist in der Regel gebaut, um das Modell selbst.
Angenommen ich habe eine app mit Konten und Transaktionen. Ich habe auch ein AccountListController, einen AccountController (das zeigt eine Konto-übersicht mit einem "alle Transaktionen" - Taste), eine TransactionListController, und ein TransactionController. AccountListController lädt eine Liste aller Konten aus und zeigt diese an. Wenn Sie Tippen Sie auf ein Listenelement, setzt es die .Konto-Eigenschaft der AccountController und schiebt den AccountController auf den Stapel. Wenn Sie Tippen Sie auf die "alle Transaktionen" - Taste, AccountController lädt die Liste Transaktion aus, stellt es in seiner TransactionListController .Transaktionen Eigentum, und schiebt die TransactionListController auf dem Stapel, und so weiter.
Wenn, sagen wir, TransactionController änderungen der Transaktion, es macht die Veränderung in seinem transaction-Objekt und ruft dann seine 'speichern' Methode 'save' sendet eine TransactionChangedNotification. Jeder andere controller, den Bedarf zu aktualisieren, selbst wenn die Transaktion änderungen beachten Sie die Benachrichtigungen und aktualisieren sich selbst. TransactionListController vermutlich würde; AccountController und AccountListController könnte, je nachdem, was Sie versuchten zu tun.
#1, zu Beginn meiner apps hatte ich eine Art von displayModel:withNavigationController: Methode in der child-controller, das würde die Dinge auf und drücken Sie den controller auf den stack. Aber wie ich schon vertrauter mit dem SDK hab ich trieb Weg von, dass, und jetzt bin ich in der Regel haben die Eltern drücken dem Kind.
Für #3, betrachten Sie dieses Beispiel. Hier sind wir mit zwei Controllern, AmountEditor und TextEditor, Bearbeiten Sie zwei Eigenschaften einer Transaktion. Die Editoren sollten eigentlich nicht speichern Sie die Transaktion bearbeitet wird, da der Benutzer entscheiden konnte, verlassen die Transaktion. Anstatt also, Sie nehmen sich beide Ihrer Eltern controller als Delegierter und rufen Sie eine Methode auf, die es sagen, wenn Sie haben nichts geändert.
Und nun ein paar Methoden aus TransactionController:
Die Sache zu bemerken, ist, dass wir definiert haben, ein generisches Protokoll, das die Redakteure verwenden können, um die Kommunikation mit Ihren owning controller. Indem Sie das tun, können wir die Wiederverwendung der Redaktion in einem anderen Teil der Anwendung. (Vielleicht Konten können mit Notizen, zu.) Natürlich, die EditorDelegate Protokoll enthalten kann mehr als eine Methode; in diesem Fall ist das nur eine notwendige.
InformationsquelleAutor der Antwort Brent Royal-Gordon
Ich sehe dein problem..
Was passiert ist, dass jemand verwechselt hat Idee der MVC-Architektur.
MVC hat drei Teile.. von Modellen, Ansichten und Controllern.. Die genannten problem zu haben scheint, kombiniert zwei von Ihnen, die für keinen guten Grund. views und Controller sind seperate Teile der Logik.
also... Sie wollen nicht zu haben, mehrere view-Controller..
möchten Sie mehrere views und ein controller, der wählt zwischen Ihnen. (Sie können auch mehrere Controller, wenn Sie mehrere Anwendungen )
Ansichten sollten NICHT Entscheidungen zu treffen. Der controller(s) machen sollte. Daher die Trennung der Aufgaben und die Logik und Möglichkeiten, machen Ihr Leben leichter.
So.. stellen Sie sicher, dass Ihre anzeigen nur das tut, macht einen schönen veiw der Daten. lassen Sie Ihre controller entscheiden, was zu tun mit den Daten, und die Ansicht zu verwenden.
(und wenn wir reden über Daten, wir sprechen über das Modell... eine schöne standard-Art zu sein storred, aufgerufen, verändert.. ein weiteres separates Stück Logik, wir können Paket Weg und vergessen)
InformationsquelleAutor der Antwort Bingy
Angenommen, es gibt zwei Klassen A und B.
Instanz der Klasse A ist
Einen aInstance;
Klasse Eine macht und eine Instanz der Klasse B, als
B bInstance;
Und in Ihrer Logik der Klasse B, irgendwo Sie sind erforderlich, um zu kommunizieren oder auslösen einer Methode der Klasse A.
1) Falsche Weg
Könnte passieren Sie die aInstance zu bInstance.
setzen Sie nun den Aufruf der gewünschten Methode [aInstance methodname] aus dem gewünschten Ort in bInstance.
Hätte dies diente Ihrem Zweck, aber während die Veröffentlichung geführt hätte, zu einem Speicher gesperrt und nicht freigegeben.
Wie?
Wenn Sie übergeben die aInstance zu bInstance erhöht den retaincount der aInstance durch 1.
Beim freigeben bInstance, wir haben den Speicher blockiert, weil aInstance können nie dazu gebracht werden, 0 retaincount von bInstance Grund dafür ist, dass bInstance selbst ist ein Objekt der aInstance.
Weiter, weil der aInstance stecken, die Erinnerung an bInstance auch geklebt werden(durchgesickert).
Auch nach der Freilassung aInstance selbst, wenn Ihre Zeit kommt später, sein Gedächtnis zu sein, wird auch gesperrt, weil bInstance kippe befreit werden und bInstance ist eine Klassenvariable der aInstance.
2)Richtigen Weg
Durch die Definition aInstance als Delegierter der bInstance, wird es keine retaincount ändern oder Speicher-Verschränkung von aInstance.
bInstance wird in der Lage sein, frei zu berufen, die delegate-Methoden liegen in der aInstance.
Auf bInstance die Freigabe, alle Variablen werden eigene erstellt und veröffentlicht werden
Auf aInstance - Freigabe, da es keine Verschränkung von aInstance in bInstance, das veröffentlicht wird sauber.
InformationsquelleAutor der Antwort rd_