10.05.2012
Xcode 4, iPhone, Cocoa Touch, iOS4, iOS5
Tutorial: UITableViewController
In diesem Tutorial wird erklärt, wie mit einem UITableViewController
eine einfach TableView erstellt. In dem Beispiel werden alle Font-Typen, die auf dem iPhone vorhanden sind, in der UITableView
angezeigt.
Die folgende Abbildung zeigt die fertige iPhone-App, die alle Font-Typen in einer UITableView
anzeigt.
Die folgende Abbildung zeigt die Architektur der fertigen App. Wie man sieht, wurde das Model-View-Controller-Pattern verwendet. Im Model werden die Font-Typen verwaltet und dem Controller bereitgestellt. Die View zeigt die Font-Typen an und benutzt für die Datenbeschaffung den Controller, d.h. die UITableViewDataSource
und den UITableViewDelegate
.
In folgenden Tutorial werden folgende Schritt durchgeführt:
- Projekt anlegen
- Model anlegen (FontModel)
- Controller anlegen (ViewController)
- View anlegen
Gestartet wird mit dem Anlegen einer iOS Application (⌘+⇧+N). In dem Fenster wählt man unter iOS den Eintrag Application aus. Als Template wird Empty Application selektiert.
Als Product Name für die App verwenden wir TableViewApp.
Abschließend wird ein Projekt-Verzeichnis gewählt.
Nach dem Klick auf Create öffnet Xcode das neue Projekt.
Nun wird das Model für die Font-Typen mit ⌘+N angelegt. In dem Fenster wählt man unter iOS den Eintrag Cocoa Touch aus. Als Template wird Objective-C class selektiert und mit Next bestätigt.
Als Namen für die Class wählt man FontModel und klickt auf Next.
Dann wird mit Create die Klasse erzeugt.
Das FontModel
benötigt zwei Methoden. Eine zum Abfragen der Anzahl der verfügbaren Fonts und eine Methode, die den Namen eines Fonts für einen Index zurückliefert. Diese Methoden werden in der Datei FontModel.h
definiert:
// // FontModel.h // TableViewApp // // Created by Jörn Hameister on 10.05.12. // Copyright (c) 2012 http://www.hameister.org. All rights reserved. // #import <Foundation/Foundation.h> @interface FontModel : NSObject -(int)countFonts; -(NSString*)fontNameAtIndex:(int)index; @end
Die Implementierung dazu sieht folgendermaßen aus:
// // FontModel.m // TableViewApp // // Created by Jörn Hameister on 09.05.12. // Copyright (c) 2012 http://www.hameister.org. All rights reserved. // #import "FontModel.h" @interface FontModel () @property (nonatomic, strong) NSMutableArray* fontList; @end @implementation FontModel @synthesize fontList = _fontList; -(NSMutableArray*) fontList { if(_fontList == nil) { _fontList = [[NSMutableArray alloc] init]; } return _fontList; } - (id)init { self = [super init]; if(self) { NSArray *families = [UIFont familyNames]; for(NSString * family in families) { NSArray *fonts =[UIFont fontNamesForFamilyName:family]; for(NSString *font in fonts) { [self.fontList addObject:[font description]]; } } } return self; } -(int)countFonts { return self.fontList.count; } -(NSString*)fontNameAtIndex:(int)index { return [self.fontList objectAtIndex:index]; } @end
Als erstes wird ein NSMutableArray
mit dem Namen fontList
angelegt, in dem die Font-Namen abgelegt werden können. Im getter wird das NSArray
einmal initialisiert. Die init
-Methode sorgt dafür, daß das NSArray
mit dem Font-Namen gefüllt wird. Dazu werden zuerst alle Font-Familien abgefragt und für jede Font-Familie, die Fonts bestimmt und deren Name in der fontList
abgespeichert.
Die beiden Interface-Methoden, die vom Controller angesprochen werden, benutzen nun einfach die fontList
um die Rückgabewerte zu bestimmen.
Nun wird ein der ViewController mit ⌘+N angelegt. In dem Fenster wählt man unter iOS den Eintrag Cocoa Touch aus. Als Template wird Objective-C class selektiert und mit Next bestätigt.
Als Namen für die Class wählt man ViewController und klickt auf Next.
Dann wird mit Create die Klasse erzeugt.
Die Datei ViewController.h
wird so erweitert, daß sie von UITableViewController
erbt und die DataSource UITableViewDataSource
implementiert. Außerdem muß eine Variable für das FontModel
anlelegt werden.
// // ViewController.h // TableViewApp // // Created by Jörn Hameister on 10.05.12. // Copyright (c) 2012 http://www.hameister.org. All rights reserved. // #import <Foundation/Foundation.h> @class FontModel; @interface ViewController : UITableViewController<UITableViewDataSource> @property (nonatomic, strong) FontModel *model; @end
Zu der UITableViewDataSource
ist anzumerken, daß die Deklaration in dieser Header-Datei auch weggelassen werden kann, weil sowohl DataSource als auch Delegate automatisch auf self
gesetzt werden, wenn zu einem ViewController keine Xib-Datei existiert.
In der Datei ViewController.m
wird nun die Variable model
des FontModel
im getter einmal initialisiert.
Als UITableViewDataSource
muß die Klasse ViewController
zumindest die Methoden tableView:numberOfRowsInSection:
und tableView:cellForRowAtIndexPath:
implementieren. Da in dem Beispiel keine sections
verwendet werden, kann der Paramenter in der ersten Methode ignoriert werden und es muß nur die Anzahl der Fonts zurückgeliefert werden. In der zweiten Methode werden die UITableViewCells
erstellt, d.h. es wird erst versucht eine Zelle aus einem "Zellenpool" mittels dequeueReusableCellWithIdentifier
zu holen und erst bei Bedarf wird eine neue Zelle erzeugt. Dieses Vorgehen ist auf einem mobilen Device sinnvoll, da bei einer sehr großen Tabelle sonst der Speicherplatz nicht ausreichend wäre. Nachdem eine UITableViewCell
verfügbar ist, wird der Font-Name im FontModel
abgefragt und als Label-Text in der Zelle gesetzt.
// // ViewController.m // TableViewApp // // Created by Jörn Hameister on 10.05.12. // Copyright (c) 2012 http://www.hameister.org. All rights reserved. // #import "ViewController.h" #import "FontModel.h" @implementation ViewController @synthesize model = _model; -(FontModel*)model { if (_model==nil) { _model = [[FontModel alloc]init]; } return _model; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.model.countFonts; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"]; if(!cell) { cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"UITableViewCell"]; } [[cell textLabel] setText:[self.model fontNameAtIndex:[indexPath row]]]; return cell; } @end
Abschließend muß nur noch die Datei AppDelegate.m
angepaßt werden, so daß der ViewController
beim Starten der App als RootViewController verwendet wird. Dazu muß die Import-Anweisung ergänzt werden und die Methode application:didFinishLaunchingWithOptions:
folgendermaßen angepaßt werden:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. ViewController* vc = [[ViewController alloc]init]; [[self window]setRootViewController:vc]; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES; }
Nach dem Kompilieren und Starten mit ⌘+R öffnet sich der Simulator und zeigt die TableView mit allen Font-Typen an.