20.11.2011

Xcode 4

Tutorial: Statische Table View (NSTableView) mit DataSource

In diesem Tutorial wird erklärt, wie eine Table View (NSTableView) mit einer Data-Source verknüpft wird, um die Zeilenweise mit Daten zu befüllen. In dem Beispiel werden die Daten, die angezeigt werden sollen, statisch in einer Datenstruktur aus NSArrays und NSDictionarys hinterlegt. In realen Applikationen würde die Table View dynamisch gefüllt werden. Beispielsweise würde man sie mit CoreData verbinden oder die anzuzeigenden Daten aus einem RSS-Feed lesen (ein solches Beispiel findet man übrigens in dem Cocoa-Kochbuch)

Gestartet wird mit dem Anlegen einer Cocoa Application (⌘+⇧+N).

Als Projektname kann beispielsweise SimpleTableView verwendet werden. In der folgenden Abbildung ist das angelegte Projekt zu sehen.

Im nächsten Dialog kann angegeben werden, in welchem Verzeichnis das Projekt abgelegt und ob zusätzlich ein lokales GIT-Repository angelegt werden soll.

Nachdem das Projekt mit Create erstellt wurde, sollte die Ansicht in Xcode folgendermaßen aussehen:

In dem Beispiel wird eine DataSource verwendet, um die NSTableView mit Daten zu befüllen. Dazu müssen zwei Methoden des Table View DataSource Protocols implementiert werden.

Die erste Methode liefert die Anzahl der Zeilen der TableView zurück.

- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView {
   ...
}
...
}

Die zweite Methode hat als Rückgabewerte den Zelleninhalt für eine Zeile mit dem Index rowIndex in einer Tabellenspalte aTableColumn.

- (id)tableView:(NSTableView *)aTableView
      objectValueForTableColumn:(NSTableColumn *)aTableColumn
      row:(NSInteger)rowIndex {
...
}

Weitere Informationen zu dem Table View DataSource Protocol findet man hier: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Protocols/NSTableDataSource_Protocol/Reference/Reference.html

Als erstes wird die Header-Datei SimpleTableViewAppDelegate.h so ergänzt, daß sie folgendermaßen aussieht:

//
//  SimpleTableViewAppDelegate.h
//  SimpleTableView
//
//  Created by Jörn Hameister on 20.11.11.
//  Copyright 2011 http://www.hameister.de . All rights reserved.
//

#import 

@interface SimpleTableViewAppDelegate : NSObject <NSApplicationDelegate> {
@private
    NSWindow *window;

    NSMutableArray* rows;
}

@property (assign) IBOutlet NSWindow *window;
@property (retain) NSArray* rows;

@end

In der Variable rows werden die Zeile der Tabelle in einem NSMutableArray abgespeichert.

In der Datei SimpleTableViewAppDelegate wird zuerst die Methode awakeFromNib hinzugefügt. In dieser Methode wird die Datenstruktur aufgebaut, die später in der NSTableView angezeigt werden soll.

- (void) awakeFromNib {
    [super awakeFromNib];
    rows = [[NSMutableArray alloc]init];

    for(int i=0; i<100;i++) {
        [rows addObject:[NSDictionary dictionaryWithObjectsAndKeys:
                         [NSString stringWithFormat:@"Name %u",i], @"Name",
                         [NSString stringWithFormat:@"Vorname %u",i], @"Vorname",
                         [NSString stringWithFormat:@"%u",i], @"Nummer",
                         nil]];
    }

}

In dem Beispiel wird zuerst die Variable rows initialisiert. Danach werden 100 Zeilen angelegt, die jeweils Name, Vorname und eine Nummer haben. Für jede Zeile wird dazu ein NSDictionary erstellt, welches als key den Namen der Tabellen-Spalte verwendet und als value einen NSString aus einen Wert und einer Nummer.

Der Grund warum eine solche Datenstruktur aus NSMutableArray und NSDictionary gewählt wurde ist, daß so sehr elegant der jeweilige Wert bestimmt werden kann. Dies wird sichtbar, wenn die eine Methode des DataSource-Protokolls implementiert wird:

- (id)tableView:(NSTableView *)aTableView
          objectValueForTableColumn:(NSTableColumn *)aTableColumn
          row:(NSInteger)rowIndex {
   return [[rows objectAtIndex:rowIndex] valueForKey:[aTableColumn identifier]];
}

Wie man sieht, wird der identifiert der Tabellenspalte als key verwendet, um aus dem NSDictionary den passenden Wert auszulesen.

Die zweite Methode des DataSource-Protokolls sieht folgendermaßen aus:

- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView {
    return [rows count];
}

Es wird einfach die Anzahl der Zeilen zurückgeliefert.

Nachdem die Implementierung jetzt fertig ist, wird die Oberfläche erstellt. Dazu wird die Datei MainMenu.xib selektiert, woraufhin sich der Interface Builder (IB) öffnet. Dort wird in der ObjectLibrary nach NSTa gesucht und die NSTableView selektiert und in das Hauptfenster (NSWindow) gezogen.

Anschließend wird jede Spalte einzeln selektiert und es wird der Title und der Identifier eingetragen:

Abschließend muß die NSTableView noch die DataSource zugeordnet bekommen. Dazu selektiert man die Tabelle und zieht den Cursor bei gedrückter Mouse-Taste auf Simple Table View App Delegate (Controller) und selektiert dataSource.

Nach dem Speichern und Kompilieren sollte die gestartete Applikation folgendermaßen aussehen: