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.
