TabBarController ohne Template

Ok, ich gebs ja zu, so ganz ohne Template gehts nun doch noch nicht. Aber versprochen, es hält sich in Grenzen und bezieht sich lediglich auf Datei- bzw. Klassentemplates.
Aber um was geht es eigentlich. Sehr viele XCode Tutorials fangen mit einer Window-Based Applikation an. Die Window Based Applikation ist ein XCode Basis Template von Apple, welches vor XCode 4.2 für so ziemlich jeden Verwendungszweck verwendet werden konnte. Seit XCode 4.2 gibt es dieses Template nicht mehr.

Und was hat das jetzt mit der TabBar zu tun? Ursprünglich war der Artikel tatsächlich einmal für die TabBar gedacht. Aber der ursprüngliche Artikel basierte auf .... na Ihr wisst schon ... genau, der Window-Based Application. Und da es diese nicht mehr gibt, erstellen wir uns kurzerhand eine Window-Based Applikation. Ich werde an gegebener Stelle auf den Beginn des eigentlichen Artikels hinweisen.
Wir fangen also mit dem Erstellen einer "Empty Application" an. Einstellungen zu der App sind erst einmal ohne Belang und sollten an anderer Stelle nachgelesen werden. Nach Erstellung der App sollten wir lediglich 2 Dateien vorfinden. AppDelegate.h und AppDelegate.m. Falls dem nicht so sein sollte -> Tonne und noch mal anfangen.

Was wir bis jetzt haben ist eigentlich nur das Grundgerüst einer Application, ohne View und Fenster. Und da wir uns ja auch etwas anzeigen lassen möchten kommt als nächstes ein View hinzu. Wir fügen uns mittels File -> New -> New File ein iOS -> User Interface -> Empty hinzu. Der Name ist auch hier erst einmal nicht entscheidend, für Nostalgiker kann man aber den Ursprünglichen Namen MainWindow verwenden. Das xib bzw. nib braucht nicht mit angehangen werden, das macht XCode für uns.

Im nächsten Schritt öffnen wir die neu erstellte Datei und wählen den File's Owner aus. Im Identity Inspector ändern wir die Class auf UIApplication und fügen uns ein Object hinzu. Die Class dieses Objects wird ebenfalls geändert. Hier wählen wir aber unsere eigene Class aus. Je nach dem wie die Application heist, sollte auch die Class des Objects lauten. Per Default ist dies AppDelegate. Nun wird es Zeit ein Window hinzuzufügen. Also holen wir uns selbiges aus der Object Library und legen es unter Objects ab
Jetzt wird es Zeit die notwendigen Verbindungen zu erzeugen.  Vorher müssen wir jedoch noch ein IBOutlet anlegen. Das machen wir per Code in der AppDelegate.h. Das anschließende Speichern der Datei ist sehr wichtig!

@interface AppDelegate :
      UIResponder <UIApplicationDelegate>
@property (nonatomic, retain) IBOutlet UIWindow *window;
@end

Wir gehen wieder zurück zur *.xib Datei und wählen den File's Owner aus. Im Connections Inspector erzeugen wir eine Verbindung vom Outlet delegate zum Object App Delegate. Dann wählen wir das Object App Delegate und erstellen die Verbindung vom Outlet window zum Object Window.

In der Projektzusammenfassung, auch Summary genannt, legen wir jetzt noch als Main Interface unser MainWindow fest und gehen anschliessend in die AppDelegate.m Datei. Diese wird wie folgt geändert:

#import "AppDelegate.h"

@implementation AppDelegate

@synthesize window;
@synthesize tabController;

- (void)dealloc {
    [window release];
    [super dealloc];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [self.window makeKeyAndVisible];
    return YES;
}

Der ganze Rest in der AppDelegate.m kann erst mal drinne stehen bleiben. Die Application ist jetzt erst einmal einsatzbereit. XCode meckert zwar beim Build das es keinen root View Controller finden kann, Ihr habt jetzt aber ein Window-Based Template worauf Ihr in den alten Tutorials aufbauen könnt.

Weiter geht's mit dem TabBarController

Aufbauend auf der Window-Based Application erstellen wir nun einen Tab Bar Controller. Unser erster Schritt wird sein, ein klein wenig Quelltext einzutippen. Die AppDelegate.h ändern wir wie folgt:

#import <UIKit/UIKit.h>

@interface AppDelegate : NSObject <UIApplicationDelegate> {
    UITabBarController *tabController;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UITabBarController *tabController;
@end

Und weil wir gerade dabei sind nehmen wir uns auch gleich noch die AppDelegate.m und ändern auch diese. Beide Dateien sollten im Anschluss auch dirkt gespeichert werden, sonst wird der Inspector in den nächsten Schritten die neu erstellten Outlets nicht finden.

#import "AppDelegate.h"

@implementation AppDelegate

@synthesize window;
@synthesize tabController;

- (void)dealloc {
    [tabController release];
    [window release];
    [super dealloc];
}

Nun wechseln wir wieder in die MainWindow.xib. Hier sollte im Dock bzw. im OutlineView ein Object "App Delegate" und ein "Window" existieren. Das Dock befindet sich zwischen der Projektübersicht und dem Editierbereich. Wir holen uns einen Tab Bar Controller aus der Object Library und legen uns diesen unterhalb von "Window" ab. Im Editierbereich sollte nun der Tab Bar Controller auftauchen. Nun klicken wir im Dock auf "App Delegate" und gehen zum Connections Inspector. Hier finden wir auch gleich unser soeben programmiertes Outlet "tabController". Dieses verbinden wir mit dem Tab Bar Controller im Dock.

Obwohl wir den Tab Bar Controller bereits im Editierbereich sehen, wird er in der App selber noch gar nicht angezeigt. Also müssen wir uns noch einmal die AppDelegate.m Datei vornehmen und die Methode application:didFinishLaunchingWithOptions entsprechend erweitern.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [self.window addSubview:tabController.view];
    [self.window makeKeyAndVisible];
    return YES;
}

Nach diesem letzten Schritt ist unsere Tab Bar auch schon fertig und einsatzbereit. Nach hinzufügen des Subviews bekommen wir beim Build auch keine Fehlermeldung, bezügl. des rootViewControllers, mehr auf der Konsole.
Aber nein, benutzen können wir die Tabs selber noch nicht. Es gibt ja keine Views dazu :-). Diese erstellen wir ganz Problemlos ohne eine einzige Zeile Code.

Es gäbe zwar die Möglichkeit einen View samt Controller zu erzeugen, jedoch krankt dies an der Dateinamensverwaltung von XCode ein wenig. Daher werden wir unsere Views und die dazu gehörigen Controller einzeln erstellen.
Zunächst erzeugen wir uns die Views mittels File -> New -> New File und wählen uns aus iOS -> User Interface das View aus. Das ganze natürlich 2x. Die Namen der Views sollten der Übersichtlichkeit halber mit treffenden Namen versehen werden. In größeren Projekten macht das durchaus auch Sinn. Der einfachheit halber nennen wir diese hier einfach nur FirstView und SecondView. Xcode erstellt uns daraufhin eine FirstView.xib sowie eine SecondView.xib.
Als nächstes erstellen wir uns die entsprechenden Controller. Wiederum mittels File -> New -> New File. Diesmal wählen wir uns jedoch aus der Gruppe COCOA TOUCH die UIViewController Subclass. Bitte darauf achten das "Witch XIB for User Interface" deaktiviert ist. Die Views haben wir ja bereits, und dies wäre auch der Schritt wenn man beides gemeinsam erstellen will. Die Namen der Classen sollten wieder treffend sein und zum View passen. Wir wählen hier die beiden Namen FirstViewController und SecondViewController.

In der Projektübersicht sehen wir nun alle neu erstellten Dateien. Nun müssen View und Controller noch mit einander verbunden werden. Dazu wählen wir die FirstView.xib und im Dock den File's Owner aus. Im Identity Inspector des File's Owner wählen wir jetzt seine Class aus. In diesem Fall ist es die von uns erstellte FirstViewController. Zum Abschluss ziehen wir noch im Connections Inspector vom Outlet view eine Verbindung zur grafischen Oberfläche. Das ganze wiederholen wir noch für den SecondView.

Zu guter Letzt verbinden wir die TabBarItems noch mit den entsprechenden Views. Hierzu gehen wir wieder zur MainWindow.xib und wählen uns das erste TabBarItem im Dock aus. Im Identity Inspector wird die FirstViewController class ausgewählt und im Attributes Inspector noch das entsprechende NIB eingetragen. In unserem Fall wäre das FirstView ohne xib.
Das wars dann auch schon und wir sind fertig. Einen weiteren Tab fügt man ganz einfach hinzu in dem man aus der Object Library ein TabBarItem in das Dock des MainWindow's zieht und entsprechend der vorliegenden Anleitung das View bzw. den Controller erstellt und mit dem TabBarItem verbindet.

Fertig! :-)