4.6 Der Pageviewcontroller
Eine weitere Möglichkeit, zwischen den Viewcontrollern einer App zu navigieren, ist eine Wischnavigation, bei der Sie auf dem Bildschirm nach rechts oder links streichen, um zur vorherigen oder nächsten Seite zu gelangen. Apple hat in iOS 5 mit der Klasse UIPageViewController einen weiteren Containerviewcontroller eingeführt, der das Blättern zwischen beliebig vielen Viewcontrollern erlaubt. Er animiert dabei den Wechsel durch eine Pagecurl-Animation, die das Umschlagen einer Buchseite (horizontales Blättern) oder eines Kalenderblattes (vertikales Blättern) nachahmt. Seit iOS 6 gibt es außerdem noch eine Scroll-Animation. Sie können eine von drei möglichen Blätterachsen wählen:
- UIPageViewControllerSpineLocationMin: der linke oder obere Rand des Views
- UIPageViewControllerSpineLocationMid: die horizontale oder vertikale Mittelachse des Views
- UIPageViewControllerSpineLocationMax: der rechte oder untere Rand des Views
Ein- und doppelseitige Darstellung
Die doppelseitige Darstellung des Pageviewcontrollers eignet sich in der Regel nur im Querformat beim horizontalen Blättern oder im Hochformat beim vertikalen Blättern. Über die Delegate-Methode pageViewController:spineLocationForInterfaceOrientation: können Sie die Bezugsposition für das Blättern bei einer Viewrotation ändern.
Abbildung 4.40 Pageviewcontroller mit zweiseitiger Darstellung
Wenn der Pageviewcontroller eine Mittelachse als Bezug verwendet, stellt er immer zwei Viewcontroller gleichzeitig dar, ansonsten nur einen. In diesem Fall können Sie eine doppelseitige Darstellung über die Property doubleSided wählen. Dann verwendet der Pageviewcontroller jeden zweiten Controller zur Darstellung der Rückseite seines Vorgängers (siehe Abbildung 4.40).
Bei der einseitigen Darstellung verwendet der Pageviewcontroller hingegen ein stark aufgehelltes, gespiegeltes Abbild der ungeraden Seiten für die Rückseiten.
Die andere Seite der Medaille
Verwenden Sie die doppelseitige Darstellung nur mit der Curl-Animation; sie macht nicht nur bei der Scroll-Animation keinen Sinn, sondern kann sogar zu Abstürzen führen.
4.6.1 Einen Pageviewcontroller erzeugen

Sie können einen Pageviewcontroller sowohl über Programmanweisungen als auch über NIBs beziehungsweise Storyboards anlegen. Falls Sie den letztgenannten Weg wählen, müssen Sie dem Pageviewcontroller indes nach der Erzeugung seine Subviewcontroller per Programmcode zuweisen. In einem Storyboard ist außerdem die Zuweisung des Delegates und einer Datenquelle notwendig, da Sie das nicht über den Interface Builder machen können. Dabei ist die Datenquelle eine Controllerkomponente, die dem Pageviewcontroller die Subviewcontroller für die Anzeige zur Verfügung stellt.
Datenquellen
Eine Datenquelle ist eine Controllerkomponente, die Objekte für einen anderen Controller bereitstellt. Dabei fragt der Controller die Datenquelle immer nur nach den Daten, die er aktuell benötigt, und er überlässt die Verwaltung der Daten komplett der Datenquelle. Dieses Vorgehen hat den Vorteil, dass die Applikation nicht die kompletten Daten im Hauptspeicher halten muss. Der Controller kann also riesige Datenmengen bei verhältnismäßig geringem Speicherverbrauch anzeigen.
Bei der Konstruktion eines Pageviewcontrollers legen Sie die Richtung und die Animation des Blätterns fest. Diese Werte können Sie später nicht mehr ändern. Als Animationstyp steht bis iOS 5 nur UIPageViewControllerTransitionStylePageCurl zur Verfügung, der ein Umblättern der Seiten simuliert. Ab iOS 6 gibt es außerdem noch den Typ UIPageViewControllerTransitionStyleScroll, der die Seiten von den Rändern her hereinschiebt.
Projektinformation
Den Quellcode des nachfolgenden Beispielprojekts finden Sie auf der DVD unter Code/Apps/Page oder im Github-Repository zum Buch im Unterverzeichnis https://github.com/Cocoaneheads/iPhone/tree/Auflage_2/Apps/Page.
Mit dem Beispielprojekt Page, das Sie auf der beiliegenden DVD finden, können Sie die verschiedenen Einstellungen eines Pageviewcontrollers ausprobieren. Es erzeugt den Controller über den in Listing 4.46 dargestellten Code.
UIPageViewControllerNavigationOrientation theOrientation =
self.selectedNavigationOrientation;
UIPageViewControllerSpineLocation theLocation =
self.selectedSpineLocation;
BOOL isDoubleSided =
self.doubleSidedControl.selectedSegmentIndex;
NSDictionary *theOptions =
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:theLocation],
UIPageViewControllerOptionSpineLocationKey, nil];
UIPageViewController *theController =
[[UIPageViewController alloc] initWithTransitionStyle:
self.animationControl.selectedSegmentIndex
navigationOrientation:theOrientation
options:theOptions];
NSArray *theControllers =
[self viewControllersForSpineLocation:theLocation];
theController.doubleSided = isDoubleSided ||
theLocation == UIPageViewControllerSpineLocationMid;
theController.dataSource = self;
theController.delegate = self;
[theController setViewControllers:theControllers
direction:self.selectedDirection animated:YES
completion:NULL];
Listing 4.46 Erzeugen eines Pageviewcontrollers
Die Bezugsposition für das Blättern übergeben Sie in einem Dictionary unter dem Schlüssel UIPageViewControllerOptionSpineLocationKey. Allerdings dürfen Sie bei der mittleren Blätterposition nur die doppelseitige Darstellung angeben. Außerdem müssen Sie die Viewcontroller setzen, die der Pageviewcontroller nach seinem Erscheinen anzeigen soll. Auch hier ist die mittlere Blätterposition ein Sonderfall, da das Array hier zwei Viewcontroller enthalten muss. Für die anderen Positionen darf das Array hingegen immer nur ein Element enthalten. Die Werte für diese Konfigurationsoptionen fasst Tabelle 4.5 noch einmal zusammen.
| Blätterposition | Rückseitendarstellung | Anzahl Viewcontroller |
|
Minimal |
Ein- und doppelseitig |
1 |
|
Mitte |
Doppelseitig |
2 |
|
Maximal |
Ein- und doppelseitig |
1 |
Listing 4.46 verwendet eine Hilfsmethode, um die Viewcontroller für die Konstruktion zu erzeugen. Die Methode viewControllersForSpineLocation: liefert ein Array mit so vielen Viewcontrollern zurück, wie in Tabelle 4.5 angegeben sind. Dieses Array übergeben Sie über die Methode setViewControllers:direction:animated:completion: an den Pageviewcontroller. Dabei sind die weiteren Parameter nur für bereits angezeigte Controller relevant. Über den Parameter animated legen Sie fest, dass die neuen Seiten durch ein Umblättern erscheinen. Die Richtung des Blätterns können Sie über den Parameter direction festlegen. Der letzte Parameter kann eine Blockfunktion enthalten, die der Controller nach Beendigung der Animation aufruft.
4.6.2 Die Datenquelle und das Delegate
Für das Blättern müssen Sie dem Pageviewcontroller jeweils die benötigten Viewcontroller für die Seiten über eine Datenquelle mit dem Protokoll UIPageViewControllerDataSource bereitstellen. Es deklariert die zwei notwendigen Methoden pageViewController:viewControllerBeforeViewController: und pageViewController:viewControllerAfterViewController:, mit denen der Pageviewcontroller jeweils auf die Vorgänger beziehungsweise Nachfolger eines Viewcontrollers zugreifen kann. Das Beispielprogramm verwendet für die Seiten einfach Viewcontroller, die eine Seitenzahl anzeigen. Die Methoden der Datenquelle erzeugen jeweils einen neuen Viewcontroller, bei dem die Seitennummer um eins niedriger beziehungsweise höher ist. Listing 4.47 enthält die Methode der Datenquelle zur Bestimmung des Vorgängers. Die Implementierung für die Bestimmung der Nachfolger ist dabei bis auf die vorletzte Zeile (+ anstatt –) gleich.
- (UIViewController *)pageViewController:
(UIPageViewController *)inPageViewController
viewControllerBeforeViewController:
(UIViewController *)inViewController {
LabelViewController *theController =
(LabelViewController *)inViewController;
return [self labelViewControllerWithPageNumber:
theController.pageNumber – 1];
}
Listing 4.47 Erzeugung des Vorgängers in der Datenquelle
Da das Projekt ein Storyboard verwendet, sollten Sie neue Viewcontroller auch darüber erzeugen. Dabei gelangen Sie an das Storyboard über die Property storyboard des Viewcontrollers. Es hat die Methode instantiateViewControllerWithIdentifier:, mit der Sie einen neuen Viewcontroller zu der angegebenen Kennung anlegen können, die Sie über das Feld Identity im Identitätsinspektor des Controllers im Interface Builder festlegen.
- (id)labelViewControllerWithPageNumber:(NSInteger)inPage {
LabelViewController *theController = [self.storyboard 
instantiateViewControllerWithIdentifier:@"label"];
theController.pageNumber = inPage;
return theController;
}
Listing 4.48 Erzeugung eines Viewcontrollers aus dem Storyboard
Der Pageviewcontroller kann bei einer Viewrotation die Blätterposition über die Delegate-Methode pageViewController:spineLocationForInterfaceOrientation: des Protokolls UIPageViewControllerDelegate ändern (siehe Listing 4.49):
- (UIPageViewControllerSpineLocation)pageViewController:
(UIPageViewController *)inPageViewController
spineLocationForInterfaceOrientation:
(UIInterfaceOrientation)inOrientation {
UIPageViewControllerNavigationOrientation theOrientation =
inPageViewController.navigationOrientation;
UIPageViewControllerSpineLocation theLocation =
[self spineLocationForInterfaceOrientation:
inOrientation
navigationOrientation:theOrientation];
NSArray *theControllers =
[self viewControllersForSpineLocation:theLocation];
[inPageViewController setViewControllers:theControllers
direction:self.selectedDirection
animated:YES completion:NULL];
return theLocation;
}
Listing 4.49 Berechnung der Blätterposition für die Viewrotation
Diese Methode liefert jedoch nicht nur die neue Blätterposition zurück. Sie muss zusätzlich dafür sorgen, dass der Pageviewcontroller die richtige Anzahl an Viewcontrollern enthält.
Ihr Kommentar
Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.





Jetzt bestellen





