NSWindowController Strategien

  • NSWindowController Strategien

    Hallo,

    meine Anwendung verteilt sich auf recht viele Nibs. Bin dazu übergegangen den "Files Owner" zu optimieren. In der Regel ist das ja ein einfacher von NSObject abgeleiteter Controller - so auch bei mir. Dann hab ich mir mal angeschaut, welche Aufgaben ich in den Controllern oft erledige und ob ich die nicht zusammenfassen könnte.

    Ich habe einige Dinge gefunden:

    In nahezu jedem Controller einer Nibfile erledige ich folgende Aufgaben:

    * irgendwelche Dinge binden
    * ein NSWindow an die Front beordern oder das NSWindow als Sheet öffnen
    * bindings eventuell wieder entfernen
    * das NSWindow/Sheet schließen

    NSWindowController konnte mir einiges an Arbeit abnehmen - allerdings nicht alles. Daher habe ich mich entschieden einen NSWindowSubclass zu machen, den dann alle Files Owner wieder subclassen.

    Nun habe ich ein NSWindowController Subclass, der mir wie folgt hilft, wenn ich ihn als Files Owner Subclass:

    Implementiere ich:

    Quellcode

    1. - (NSString *)windowNibName
    2. {
    3. return @"CardShowPreferences";
    4. }


    Wird logischerweise automatisch die entsprechende Nib geladen.

    Frage: NSWindowController hat auch ein init dafür:

    Quellcode

    1. - (id)initWithWindowNibName:(NSString *)windowNibName


    Ich initialisiere meine Windowcontroller aber immer mit [[MeinWindowController alloc] init]. Mir gefällt es nicht, dass mein Hauptcontroller, der alle anderen WindowController kennt auch noch deren Nibnamen kennen muss. Allerdings muss die initWithWindowNibName auch einen Sinn haben, den ich momentan nicht sehe. Außerdem habe ich in fremdem Code gesehen, dass eigentlich nur mit initWithWindowNibName gearbeitet wird und dem Subclass die Arbeit abgenommen wird.

    Zweite Frage: Mein NSWindowController Subclass, der von allen anderen NSWindowController gesubclassed wird hat eine methode setIsSheet:(BOOL). Zusätzlich dazu hat er eine Action: hide:. Ist isSheet == YES, dann öffnet der Controller das zugewiesene NSWindow als sheet, sobald showWindow: aufgerufen wird. Ist dies nicht der fall wird [super showWindow:] aufgerufen. Bei hide: ebenso nur, dass da das Fenster natürlich verschwindet - entweder als sheet oder als Fenster. Ist das ein gangbarer Weg? Zu umständlich gemacht?

    Dritte Frage: Früher hatte ich in meinen inits/awakeFromNibs alles möglich untergebracht, was da eben so reingehört. Das habe ich schon vor einigen Monaten geändert. Jedes awakeFromNib sah in etwa dann so aus:

    Quellcode

    1. - (void)awakeFromNib
    2. {
    3. [self createObjects];
    4. [self setupUI];
    5. [self setupBinding];
    6. [self showWindow];
    7. }


    Nun habe ich einfach in meinen "abstrakten" NSWindowControllerSubclass zwei Methoden definiert nämlich setupUI und setupBindings, die er automatisch aufruft, sobald es zeit dazu ist.

    In meinen konkreten NSWindowControllerSubclasses kann ich dann einfach je nach bedarf setupBindings bzw. setupUI implementieren oder es sein lassen. Erachtet ihr das eher als sinnvoll? Last? Umständlich?

    Ich hoffe ich liege mit meinen Strategien mir das Leben einfacher zu machen nicht ganz falsch. Aber ihr wisst, dass ich nicht so die Erfahrung mit Cocoa habe und ich bin mir sicher, dass ich vieles zu umständlich gemacht habe. Wäre schön, wenn man das hier ausräumen könnte.

    Wie geht ihr mit diesen immer wiederkehrenden Dingen um?
    Die Objective-Cloud ist fertig wenn sie fertig ist. Beta heißt Beta.

    Objective-C und Cocoa Band 2: Fortgeschrittene
    Cocoa/Objective-C Seminare von [co coa:ding].
  • RE: NSWindowControllers Strategien

    Ich habe auch eine allgemeine Subklasse von NSWindowController in meinem Projekt. In der Tat gibt es da viel Gemeinsames.

    Ein paar Gedanken:
    a) Designated Initializer
    Der -initWithNibName: ist in der Tat etwas schief. Wann will man schon den WC A mit dem Nibfile B instantieren? Es scheint mir auch eine Eigenschaft des Window-Controllers zu sein, welchen Nib er benutzt. Eine "saubere" Implementierung wäre es wohl gewesen, dass der designated Initializer von NSWindowController -init heißt und eine eigene Methode -nibName aufruft. Diese wäre jedoch in der Basisklasse virtuell gewesen, so dass man jedesmal hätte ableiten müssen. Und gerade am Anfang eines Projektes oder bei einfachen Fenstern (Keine Toolbars, keine besonderen Bindungen) ist das häufig nicht notwendig. Ich tendiere aber auch immer mehr dazu. Was kosten mich schon 3, 4 Zeilen?

    Du kannst ja ohne Not in deiner Subklasse einen neuen designated Initializer bestimmen. Das verbietet dir niemand! Das musst du natürlich dokumentieren.

    b) Auto-Show und -Hide
    Ich weiß nicht, ob sich das lohnt -- Tatfrage.

    c) setUp-Methoden
    Ich würde dann schon eher das awakeFromNib allgemein die Methoden aufrufen lassen, die in der Basis-Implementierung nichts tun. Aber insgesamt schmeckt mir das nicht so gut, weil es ja sein kann, dass es einen Bedeutungszusammenhang gibt, etwa zwischen Objects und Bindings. Dann sortiere ich das lieber nach dem Thema, nicht nach der Aufgabe. Aber Geschmäckle ...

    Für das Verhältnis von allgemeinem zu speziellen Code gibt es ja nun verschiedene Systeme, die wohl wichtigsten:
    - Subclassing
    - Delegating
    - Meinetwegen Notifications

    Was, wann am besten ist, darüber gibt es sicherlich so viele Ansichten wie Sandkörner am Meer. Ich denke, dass kann man nicht allgemein beantworten. Man muss siich bei seiner Entscheidung halt bewusst machen, was am besten passt und am wenigsten verbaut.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • zu b: Was meinst du damit?

    zu c: "Ich würde dann schon eher das awakeFromNib allgemein die Methoden aufrufen lassen, die in der Basis-Implementierung nichts tun." - ich habe während du deinen Beitrag geschrieben hast meinen korrigiert:

    "In meinen konkreten NSWindowControllerSubclasses kann ich dann einfach je nach bedarf setupBindings bzw. setupUI aufrufen oder es sein lassen."

    wurde zu:

    "In meinen konkreten NSWindowControllerSubclasses kann ich dann einfach je nach bedarf setupBindings bzw. setupUI implementieren oder es sein lassen."

    Hat dich das irritiert?
    Die Objective-Cloud ist fertig wenn sie fertig ist. Beta heißt Beta.

    Objective-C und Cocoa Band 2: Fortgeschrittene
    Cocoa/Objective-C Seminare von [co coa:ding].
  • b)
    Na, wenn ich das richtig verstehe, dann willst du eine allgemeine Antwort auf die Frage des Öffnen des Fensters implementieren, oder? Wozu? Das Fenster wird wohl in 90 % der Fälle geöffnet. Und du ersparst dir einen Aufruf.

    c)
    Ah, verstehe. Na, dann ist es ja so wie meine Ansicht.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?