2010-05-18 5 views
6

Haben Sie Tricks oder Techniken, um Cocoa-Controller-Klassen in kleinere Blöcke zu zerlegen? Ich finde, dass, was auch immer ich mache, die Controller zu einer der komplizierteren Klassen in meinem Design gehören. Das grundlegende Zeug ist einfach, aber sobald ich mehrere Pop-Overs oder Action-Sheets laufen habe, werden die Dinge unangenehm komplex. Es ist nicht , dass schlecht, aber immer noch möchte ich den Code in mehrere eigenständige Teile umgestalten.Wie halten Sie Cocoa-Controller davon ab, zu groß zu werden?

Ich habe über Kategorien nachgedacht, aber der Code ist nicht so unabhängig (viele Male muss er in viewWillAppear zum Beispiel tippen) und ich finde, dass ich eine lange Zeit damit verbringe, den Compiler zu bekämpfen. Ich habe auch darüber nachgedacht, Funktionalität in Schichten durch Vererbung hinzuzufügen, aber das fühlt sich an wie ein Hack.

+0

Ich bin nicht vertraut mit Cocoa, aber ich habe das gleiche "Problem" in PHP mit dem MVC-Setup, also denke ich, es gilt auch für verschiedene Sprachen. Ich habe über Sub-Controller für verschiedene Teile nachgedacht, aber das würde das Ganze nur viel komplexer machen. Und auf diese Weise können Sie im Grunde weiter bohren, bis Sie einen Sub-Sub-Sub-Sub-Controller haben, wenn Sie etwas Großes schreiben, und das wird nur sehr schwer zu pflegen. Neugierig zu sehen, welche Lösungen kommen :) – Alec

Antwort

4

Das Problem ist nicht Größe, sondern Verantwortung. Trägt Ihr Controller mehr als einen Hut? Wenn ja, sprengen Sie es in mehrere Controller für einen Job pro Klasse.

Kategorien helfen mit Größe, aber nicht Verantwortung. Wenn Sie immer noch mehrere Dinge in einer (amalgamierten) Klasse machen, dann haben Sie immer noch ein Problem; Verschieben sie in separate Dateien hat es nicht gelöst.

Wenn viele Kategorien in einer einzigen Klasse enthalten sind, besteht das Risiko von Methodenkollisionen: Die gleiche Methode wird in mehreren Kategorien implementiert, wahrscheinlich durch die Implementierung in Kategorie B. Vergessen Sie jedoch, dass Kategorie A bereits vorhanden ist. Dies führt zu einem Problem, wenn das Objekt sich selbst eine Nachricht sendet, die Antwort einer Kategorie auf diese Nachricht erwartet und die andere bekommt.

Die Deklaration aller der Kategorien im Hauptklassenkopf mildert dieses Risiko, da Sie sehen können, dass eine andere Kategorie bereits eine Methode mit dem Namen hat, den Sie eingeben möchten. Jede Methode, die Sie hinzufügen und dadurch die Header-Datei verlängert, verringert jedoch die Mitigation.

Wenn Ihr Controller mehr als einen Hut trägt, teilen Sie ihn in mehrere Klassen auf.

Ich empfehle Martin Fowlers Buch "Refactoring". Refactoring Ihres Codes ist es zu bereinigen, und zu große Klassen (und Methoden und Funktionen) in die Luft zu sprengen ist eine Teilmenge solcher Aufräumarbeiten.

Natürlich, mehrere Klassen, die einmal eins waren, benötigen einen Ersatz für die Kommunikation, die zuvor intern innerhalb der Klasse war.Cocoa bietet eine Reihe von Lösungen:

Sie brauchen nicht um genau einen auszuwählen, noch müssen Sie sie alle benutzen. Welche Lösungen angemessen sind, hängt davon ab, welche Kommunikationsanforderungen Ihre neuen Klassen haben müssen.

+0

Blöcke machten mein Leben viel einfacher, weil ich die Delegierungsmethoden wie die, die von Pop-Overs und Action-Sheets (zum Beispiel http://github.com/zoul/Lambda- Aufmerksam). Ich kann nicht warten, bis Blöcke auf dem iPad erscheinen, ich hätte nicht gesagt, dass sie einen Unterschied machen. – zoul

3

Kategorien ist der Weg zu gehen. Der Trick (für Ihre "nicht so unabhängigen" Sachen) besteht darin, die Kategoriemethoden in Ihrer Hauptcontroller-.h-Datei zu deklarieren (nicht eine separate Controller + category.h-Datei, es wird keine geben), dann implementieren Sie sie in Ihrer Controller + -Kategorie. m Datei. Wie folgt aus:

//****************** 
// MyController.h 
//****************** 
#import <Cocoa/Cocoa.h> 

@interface MyContoller : NSObject 
{ 
    NSWindow *window; 

    // stuff to implement in the category 
    NSComboBox *someCombo; 
    NSButton  *someButton; 
} 

@property IBOutlet NSWindow *window; 

@property IBOutlet NSComboBox *someCombo; 
@property IBOutlet NSButton *someButton; 

@end 

@interface MyController (MyCategory) 

- (IBAction)someComboSelected:(id)sender; 
- (IBAction)someButtonPressed:(id)sender; 

@end 

//************************** 
// MyController+MyCategory.m 
//************************** 
#import <Cocoa/Cocoa.h> 
#import "MyController.h" 

@implementation MyContoller (MyCategory) 

- (IBAction)someComboSelected:(id)sender 
{ 
    .... 
} 

- (IBAction)someButtonPressed:(id)sender 
{ 
    .... 
} 

Offensichtlich enthalten ich nicht „MyController.m“, in dem Sie das „@synthesize“ Zeug legen und was sonst benötigt wird, um für die Hauptsteuerung/wach-from-nib/was auch immer. Auf diese Weise erhalten Ihre Controller-Methoden Zugriff auf die Kategorienmethoden und umgekehrt, und die Kategoriemethoden haben Zugriff auf alle Eigenschaften.

2

In regulärem Cocoa kann NSViewController verwendet werden, um die Controller-Komplexität zu verwalten, indem "Komponenten" innerhalb eines Fensters ihre eigenen Gesamt-Controller erhalten.

Möglicherweise können Sie mit UIViewController etwas Ähnliches tun, oder Sie möchten "koordinierende Controller" außerhalb Ihrer View-/View-Controller-Hierarchie erstellen, um das Verhalten Ihrer Modellobjekte separat zu verwalten.

Verwandte Themen