42 Stimmen

NSWindowController Klärung des Verständnisses

Ich habe NSWindowController in mehreren Projekten verwendet und habe das Gefühl, dass ich ein (sehr) grobes Verständnis der Konzepte hinter dieser wichtigen Klasse habe. Was ich mit diesem Beitrag erreichen möchte, ist meine eigenen Erkenntnisse zu klären/korrigieren und hoffentlich anderen Lernenden zu helfen, den ersten Schritt zum Verständnis zu machen. Es sind die auf einen Blick Konzepte, Übersichten und bewährten Verfahren, die ich am nützlichsten finde und die in der Dokumentation oft fehlen. Hier ist meine Ansicht zu NSWindowController (Fragen sind fett hervorgehoben):

  • Ein NSWindowController (NSWC) Unterklasse existiert (konzeptionell) direkt unter jedem Fenster-Nib und fungiert als Bindeglied zwischen den Benutzeroberflächenelementen und den Modellobjekten, die sie steuern/darstellen. Grundsätzlich sollte jedes Fenster in Ihrer Anwendung eine eigene NSWC Unterklasse haben.
  • Der File's Owner des Nibs sollte immer die NSWC Unterklasse sein. Ist dies auch der Fall für die MainMenu.xib Anwendung?
  • Das NSWC window Eigenschaft sollte immer mit dem NSWindow in InterfaceBuilder verknüpft sein.
  • Sie sollten die 'init' Methode überschreiben und [super initWithWindowNibName:] verwenden, damit beim Verweisen auf [mycontroller window] das Nib geladen wird. Sollte dies auch für den NSWC für das MainMenu.xib Fenster der Fall sein, obwohl dies beim Start geöffnet wird?
  • Der NSWC sollte nicht zu viele Aufgaben übernehmen - er sollte einfach Nachrichten an Instanzen von Objekten übergeben und diese Objekte in der Benutzeroberfläche präsentieren.
  • Es kann die Benutzeroberfläche über Bindung modifizieren, als Delegierter für Tabellen fungieren usw. oder aktiv die Benutzeroberflächenelemente ändern, wenn es eine Änderung beobachtet, oder eine Kombination aus all dem (welche Methode Sie verwenden, scheint eine Frage des Geschmacks zu sein, mit Vor- und Nachteilen auf allen Seiten).
  • Ein NSWC kann bei Bedarf Instanzen anderer NSWCs erstellen (zum Beispiel beim Öffnen eines einmaligen Unterfensters).
  • Verwenden Sie [mycontroller showWindow:nil], um das zugehörige Fenster vorne anzuzeigen. Wenn Sie möchten, dass das Fenster als Blatt erscheint, verwenden Sie etwas wie:

    NSWindowController* mycontroller = [[MyController alloc] init];
    [NSApp beginSheet: [mycontroller window]
       modalForWindow: [self window] 
        modalDelegate: self 
       didEndSelector: @selector(didEndMySheet:returnCode:contextInfo:)
          contextInfo: nil];

Das didEndSelector: sollte eine Methode des NSWC des übergeordneten Fensters sein und kann auf 'mycontroller' mit [sheet windowController]performClose: des NSWC-Fensters auf.

Einige Fragen:

  • Sollte der NSWC des MainMenu-Fensters auch der Anwendungsdelegierte sein oder sollte dies eine andere Klasse sein?
  • In gleicher Weise, sollte der Haupt-NSWC Dateien (Drag & Drop und Öffnen) bearbeiten oder sollte dies an den Anwendungsdelegierten weitergeleitet werden, oder ist das nur eine Frage des Geschmacks?

Bitte korrigieren Sie mich, wenn etwas davon schlechte Praxis ist oder einfach falsch. Ich möchte mein Verständnis von NSWindowController klären, daher wären alle Ergänzungen (in Form von bewährten Verfahren, Erfahrungen, Vorsichtsmaßnahmen) sehr willkommen.

Vielen Dank, Laurie

30voto

Sven Punkte 22195

Wofür sind Fenster-Controller eigentlich da?

Fenster-Controller sind Tools zum Laden eines Fensters aus einer NIB-Datei und zum Verwalten des Speichers der in der NIB allokierten Ressourcen. Bevor es NSWindowControllers gab, musste man im Grunde genommen den gleichen Code für jedes Fenster schreiben oder eine eigene Fenster-Controller-Klasse erfinden.

Natürlich sind sie auch Controller im Sinne des Model/View/Controller, also der richtige Ort, um die Views des Fensters mit den Model-Objekten zu verbinden. Dazu müssen sie oft als Delegat oder Datenquelle für ein View-Objekt fungieren. Also hast du diesen Teil perfekt verstanden.

Außerdem sind Fenster-Controller ein Werkzeug für die Code-Wiederverwendung. Es macht es einfach, die Fenster-Controller-Klasse und ihre XIB/NIB in ein anderes Projekt einzufügen und dort zu verwenden.

Ja, jedes Fenster aus einer NIB sollte also von einem Fenster-Controller verwaltet werden, mit einer Ausnahme. Tatsächlich handelt es sich dabei nur um eine Richtlinie für guten Code, die nicht erzwungen wird.

Fenster-Controller und MainMenu.xib

MainMenu.xib ist etwas anderes, dort kann man keinen Fenster-Controller verwenden. Diese NIB wird von NSApplication geladen, daher muss sie der "Files Owner" sein. Es gibt keinen Weg, einen Fenster-Controller zwischen NSApplication und der NIB zu platzieren. Es ist auch nicht notwendig, dort einen Fenster-Controller für die Speicherverwaltung zu verwenden, da das Anwendungsobjekt für die gesamte Laufzeit des Programms existiert und daher seine Ressourcen aus der NIB nicht aufräumen muss, wenn es deallokiert wird.

Wenn du wirklich einen Fenster-Controller für dein Hauptfenster benötigst, kannst du dies nicht in das MainMenu.xib setzen.

Ich hoffe, das hilft. Es gibt wahrscheinlich noch viel mehr über Fenster-Controller zu sagen

7voto

geowar Punkte 4294

Ist das auch der Fall für die MainMenu.xib-Anwendung?

Nein, das MainMenu-NIB gehört zu NSApplication (das lädt es).

Sollte das auch für die NSWC für das MainMenu.xib-Fenster gelten, auch wenn es beim Start geöffnet wird?

Nein, NSApplication lädt das Haupt-NIB basierend auf der "NSMainNibFile"-Eigenschaft Ihrer Anwendungsdatei. (Das ist nur voreingestellt auf "MainMenu" in den Vorlagen-Xcode-Projekten.) Wenn Sie dessen Namen ändern möchten, ändern Sie es dort (und benennen Sie Ihre NIB-Datei um). (Übrigens: Diese Eigenschaft kann auch in der "Zusammenfassung" Ihres Ziels in Xcode 4 geändert werden.)

Sollte die NSWC des MainMenu-Fensters auch der Anwendungsdelegierte sein, oder sollte dies eine andere Klasse sein?

Der Eigentümer des NSMainNibFile-NIBs ist die Instanz von NSApplication, die es lädt, und damit auch ein Delegierter dieser Instanz. Weder von ihnen sind NSWC-Subklassen.

Sollte der Haupt-NSWC auch Dateien (Drag & Drop und Öffnen) behandeln oder sollte dies an den App-Delegierten weitergeleitet werden oder ist das nur eine Geschmacksfrage?

Es gibt keinen "Haupt-NSWC" (Die App-/App-Delegierter ist der Controller für das NSMainNibFile).

Alle Drag-and-Drop-Vorgänge werden von NSWindow- oder NSView-Subklassen behandelt. Ich verwende normalerweise eine spezielle NSWindow- oder NSView-Subklasse, die einfach alle Drag-and-Drop-Methoden an den Delegierten weiterleitet. Zum Beispiel:

- (unsigned int) draggingEntered:sender
{
    return [[self delegate] draggingEntered:sender];
}

Auf diese Weise kann ich alle meine Fenster-/View-Code zusammen in ihren jeweiligen Controllern halten (wie von deren NIB-Besitzer bestimmt). Und weil der fenster-/View-spezifische Code im Controller (nicht in der NSWindow-/NSView-Subklasse) ist, können verschiedene Arten von NSWindows/NSViews alle dieselben Drag-and-Drop-Subklassen verwenden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X