Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Geleitwort
Vorwort
1 Hello iPhone
2 Die Reise nach iOS
3 Sehen und anfassen
4 Alles unter Kontrolle
5 Daten, Tabellen und Controller
6 Models, Layer, Animationen
7 Programmieren, aber sicher
8 Datenserialisierung und Internetzugriff
9 Multimedia
10 Jahrmarkt der Nützlichkeiten
Stichwort

Buch bestellen
Ihre Meinung?

Spacer
Apps programmieren für iPhone und iPad von Klaus M. Rodewig, Clemens Wagner
Das umfassende Handbuch
Buch: Apps programmieren für iPhone und iPad

Apps programmieren für iPhone und iPad
Rheinwerk Computing
1172 S., geb., mit DVD
49,90 Euro, ISBN 978-3-8362-2734-6
Pfeil 4 Alles unter Kontrolle
Pfeil 4.1 Viewcontroller, XIBs und Storyboards
Pfeil 4.1.1 Erstellung von Viewcontrollern über XIB-Dateien
Pfeil 4.1.2 Applikationsinitialisierung
Pfeil 4.1.3 Storyboards
Pfeil 4.1.4 Modale Dialoge
Pfeil 4.1.5 Pop-over
Pfeil 4.1.6 Übergänge
Pfeil 4.2 Der Navigationcontroller
Pfeil 4.2.1 Viewcontroller anzeigen und entfernen
Pfeil 4.2.2 Die Navigationsleiste
Pfeil 4.2.3 Der Zurück-Button
Pfeil 4.2.4 Gehe drei Felder zurück
Pfeil 4.2.5 Die Werkzeugleiste
Pfeil 4.3 Navigation- und Pop-over-Controller in der Praxis
Pfeil 4.3.1 Navigationcontroller anlegen
Pfeil 4.3.2 Einen Dialog für die Einstellungen gestalten
Pfeil 4.3.3 Früher war alles besser ...
Pfeil 4.3.4 Einstellungen dauerhaft speichern
Pfeil 4.3.5 Storyboard lokalisieren
Pfeil 4.3.6 Anpassung an das iPad
Pfeil 4.4 Der Splitviewcontroller
Pfeil 4.4.1 Das Splitviewcontroller-Delegate
Pfeil 4.4.2 Eine Projektvariante erstellen
Pfeil 4.4.3 Rotationsverhalten für einzelne Viewcontroller ändern
Pfeil 4.4.4 Anlegen eines Splitviewcontrollers
Pfeil 4.4.5 Autolayout-Restriktionen per Programmcode erstellen
Pfeil 4.4.6 Anzeige des Masters
Pfeil 4.5 Der Tabbarcontroller
Pfeil 4.5.1 Aufbau einer Reiternavigation
Pfeil 4.5.2 Plaketten
Pfeil 4.5.3 Für ein paar Controller mehr
Pfeil 4.6 Der Page-Viewcontroller
Pfeil 4.6.1 Einen Page-Viewcontroller erzeugen
Pfeil 4.6.2 Die Datenquelle und das Delegate
Pfeil 4.7 Eigene Container- und Subviewcontroller
Pfeil 4.7.1 Container- und Subviewcontroller
Pfeil 4.7.2 Verwaltung der Subviewcontroller
Pfeil 4.7.3 ContainerViews leicht gemacht
Pfeil 4.8 Regelbasierte Anpassung der Oberfläche
Pfeil 4.8.1 Gestaltungsregeln ...
Pfeil 4.8.2 ... und Gestaltungsmöglichkeiten

4Alles unter KontrolleZur nächsten Überschrift

»Liebe Mari, ich bin so froh’, daß ich keine Rede nicht halten brauch’, sondern das Maul.«
– Ludwig Thoma

Im MVC-Muster nimmt die Controller-Schicht eine zentrale Rolle ein. Sie haben im dritten Kapitel bereits mit zwei Klassen aus dieser Schicht – dem App-Delegate und einem Viewcontroller – intensiv gearbeitet. Dabei sind Viewcontroller für die Steuerung und das Zusammenspiel der Views und der Nutzereingaben verantwortlich.

Übersichts- und Grundlagenkapitel

Dieses Kapitel stellt verschiedene Viewcontroller-Klassen des Systems vor und zeigt ihre Anpassungsmöglichkeiten auf. Diese Viewcontroller sind wichtige Bausteine für alle iOS-Apps. Ein weiteres wichtiges Thema dieses Kapitels sind Storyboards und deren Unterschiede zu XIB- beziehungsweise NIB-Dateien. Der analoge Wecker dient dabei als Basis für Programmbeispiele für einen Teil der Projekte. Außerdem gibt es einige Programmbeispiele für die Themen, die sich nicht über das Wecker-Beispiel sinnvoll abbilden lassen. Zu diesen Themen folgen in den nächsten Kapiteln allerdings noch größere Beispiele.


Rheinwerk Computing - Zum Seitenanfang

4.1Viewcontroller, XIBs und StoryboardsZur nächsten ÜberschriftZur vorigen Überschrift

Größere Apps stellen in der Regel mehrere Ansichten dar, und es wäre sehr unpraktisch, wenn deren Verwaltung über nur einen Viewcontroller erfolgen müsste. Stattdessen können und sollten Sie jeden Dialog auch über einen eigenen Viewcontroller verwalten. Als Dialog bezeichnen wir dabei im Folgenden eigenständige View-Hierarchien; also die View-Hierarchien der App, die jeweils für sich allein eine sinnvolle Ansicht beziehungsweise Eingabemaske bilden.

Die folgenden Abschnitte zeigen Ihnen, wie Sie die Erzeugung von Viewcontrollern in XIB-Dateien auslagern und XIB-basierte Projekte auf Storyboards umstellen können. Diese Aufgaben treten zwar in der Praxis eher selten auf; bei der Durchführung lernen Sie jedoch noch einige nützliche Details über die Architektur von Cocoa-Touch-Apps kennen.

Erinnerung: XIB- und NIB-Dateien

Xcode wandelt bei der Erstellung einer Applikation alle XIB-Dateien in die wesentlich kompakteren NIB-Dateien um. Wir verwenden den Begriff XIB, wenn wir uns auf die Datei im Projekt beziehen. Die entsprechende Datei im Programm bezeichnen wir hingegen als NIB.


Rheinwerk Computing - Zum Seitenanfang

4.1.1Erstellung von Viewcontrollern über XIB-DateienZur nächsten ÜberschriftZur vorigen Überschrift

Obwohl Storyboards die XIB-Dateien immer mehr verdrängen, gibt es dennoch einige gute Gründe, sich damit auseinanderzusetzen. Viele Beispielprojekte, die Sie im Netz finden, basieren auf XIB-Dateien. Außerdem kann es durchaus sinnvoll sein, den View eines einzelnen Viewcontrollers in einer XIB-Datei anstatt in einem Storyboard abzulegen; denken Sie hierbei beispielsweise an eine Komponente, die Sie in mehreren Projekten verwenden wollen. Hier ist die Ablage des Views in einer XIB-Datei sehr praktisch, da Sie diese Datei zusammen mit der Klasse des Viewcontrollers relativ einfach in ein anderes Projekt integrieren können.

In den meisten Fällen erzeugen Sie Viewcontroller, indem Sie entweder ein neues Objekt über eine alloc-init-Kette anlegen oder Sie diese aus einer NIB-Datei beziehungsweise einem Storyboard laden. Die erste Alternative sieht im Programmcode so aus:

AlarmClockViewController *theController = 
[[AlarmClockViewController alloc]
initWithNibName:@"AlarmClockViewController"
bundle:nil];

Listing 4.1 Anlegen eines Viewcontroller-Objekts

Wenn die NIB-Datei wie die Viewcontroller-Klasse ohne die Endung »Controller« heißt oder den gleichen Namen wie die Viewcontroller-Klasse hat, können Sie auch einfach die Methode init verwenden. Damit sucht der Viewcontroller nach diesen NIB-Dateien in dieser Reihenfolge. Für den AlarmClockViewController bedeutet das also, dass der über

AlarmClockViewController *theController = 
[[AlarmClockViewController alloc] init];

erzeugte Viewcontroller, zuerst nach der NIB-Datei AlarmClockView.nib und, falls diese nicht existiert, nach AlarmClockViewController.nib sucht.

Cocoa Touch verwendet den Viewcontroller beim Laden als Eigentümer oder auch Files Owner der NIB-Datei. Wenn Sie einen Viewcontroller mit eigener XIB-Datei anlegen wollen, geht das am einfachsten über das Erstellen einer neuen Klasse. Wenn Sie im zweiten Schritt UIViewController [Anm.: Oder eine Unterklasse davon] als Oberklasse für die neue Klasse auswählen, können Sie Xcode über die Option With XIB for user interface anweisen, auch eine XIB-Datei anzulegen (siehe Abbildung 4.1).

Abbildung

Abbildung 4.1 Anlegen einer Viewcontroller-Klasse mit XIB-Datei

Xcode weist in der neuen XIB-Datei dabei auch dem File’s-Owner-Platzhalter die Klasse des Eigentümers, also die Klasse des neuen Viewcontrollers, zu. Diese Zuweisung ist für die weitere Arbeit mit der XIB-Datei wichtig, damit der Interface Builder die Outlets und Actions des Eigentümers ermitteln kann. Abbildung 4.2 zeigt eine XIB-Datei im Interface Builder. Den Platzhalter für den Eigentümer sehen Sie in der linken Spalte als oberstes Objekt und die Klasse des Eigentümers im Identitätsinspektor auf der rechten Seite.

Abbildung

Abbildung 4.2 XIB-Datei im Interface Builder

Sie können auch nachträglich zu einer existierenden Viewcontroller-Klasse eine XIB-Datei anlegen. Dazu starten Sie in Xcode den bekannten Assistenten zum Anlegen einer neuen Datei, wählen auf der linken Seite die Rubrik User Interface und aus den Vorlagen View (siehe Abbildung 4.3).

Abbildung

Abbildung 4.3 Anlegen einer neuen XIB-Datei in Xcode

Nach Beendigung des Assistenten sollten Sie dem Eigentümer der neuen XIB-Datei über dessen Identitätsinspektor die Klasse des Viewcontrollers zuweisen.

Unabhängig davon, wie Sie die Klasse des Viewcontrollers und dessen XIB-Datei angelegt haben, können Sie nun den View in der XIB-Datei wie gewohnt mit Subviews befüllen und konfigurieren. Wenn Sie einen neuen Viewcontroller wie oben beschrieben anlegen, lädt dieser seinen View aus der NIB-Datei.


Rheinwerk Computing - Zum Seitenanfang

4.1.2ApplikationsinitialisierungZur nächsten ÜberschriftZur vorigen Überschrift

Eine iOS-Applikation besitzt in der Regel drei Objekte, die sie beim Start erzeugt: das Application-Delegate, einen initialen Viewcontroller und das Applikationsfenster. Das Applikationsfenster hat die Klasse UIWindow und dient zur Anzeige der Views. Bei der App-Programmierung spielt es im Allgemeinen keine nennenswerte Rolle. Apple hat das Vorgehen, wie Apps diese Objekte erzeugen, im Laufe der Zeit zweimal verändert. Es gibt drei Varianten, wie eine Applikation ihre Grundobjekte anlegt. Unter Xcode 5 können Sie jedoch neue Projekte nur noch auf Basis von Storyboards anlegen. Trotzdem können Sie natürlich noch ältere Projekte mit XIB-Dateien in Xcode öffnen, bearbeiten und ausführen.

In Tabelle 4.1 finden Sie eine Übersicht, welche Komponenten die einzelnen Grundobjekte der Applikation erzeugen. Dabei hat Apple mit Xcode 4.2 das Vorgehen für die Initialisierung bei der Verwendung von XIB-Dateien verändert: Die Grundobjekte, die in den Vorversionen noch die Datei MainWindow.xib erzeugt hat, legen nun Programmanweisungen an. Dabei ist das im Fall des Application-Delegates nur die Angabe der Klassenamens als letzter Parameter im Aufruf der Funktion UIApplicationMain (siehe Listing 4.2).

Tabelle 4.1 Erstellungsorte der Grundobjekte

Grundobjekt XIB-Dateien Storyboard
< Xcode 4.2 ≥ Xcode 4.2

Application-Delegate

MainWindow.xib

UIApplicationMain

initialer Viewcontroller

Application-Delegate

Storyboard

Applikationsfenster

Application-Objekt

int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil,
NSStringFromClass([AlarmClockAppDelegate class]));
}
}

Listing 4.2 Initialisierung der Applikation

In den drei Varianten unterscheiden sich die Implementierungen der Delegate-Methode application:didFinishLaunchingWithOptions voneinander. Während sie bei einer App mit Storyboard nur ein return YES; enthält, enthalten die XIB-basierten Varianten noch weitere Anweisungen. Wenn das Projekt eine MainWindow.xib-Datei besitzt, muss die Delegatemethode den initialen Viewcontroller an das Fenster übergeben, das Fenster anzeigen und in den Vordergrund bringen. Den entsprechenden Code finden Sie in Listing 4.3.

- (BOOL)application:(UIApplication *)inApplication 
didFinishLaunchingWithOptions:(NSDictionary *)inOptions {
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}

Listing 4.3 Initialisierung des deserialisierten Fensters

Bei XIB-basierten Projekten ohne MainWindow.xib muss die Delegate-Methode zusätzlich den initialen Viewcontroller und das Fenster erzeugen. Diese zusätzlichen Schritte stellt Listing 4.4 hervorgehoben dar.

- (BOOL)application:(UIApplication *)inApplication 
didFinishLaunchingWithOptions:(NSDictionary *)inOptions {
self.window = [[UIWindow alloc] initWithFrame:
[[UIScreen mainScreen] bounds]];
self.viewController = [[ViewController alloc]
initWithNibName:@"ViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}

Listing 4.4 Erzeugung des Fensters und des initialen Viewcontrollers


Rheinwerk Computing - Zum Seitenanfang

4.1.3StoryboardsZur nächsten ÜberschriftZur vorigen Überschrift

Apple hat Storyboards erst mit iOS 5 eingeführt, und in Xcode 4, also bis iOS 6.1, konnte man beim Anlegen eines neuen Projekts noch frei zwischen XIBs oder Storyboards als Basis wählen, und so entwickelten viele Programmierer zunächst ihre Projekte auch weiterhin auf der Basis von XIB-Dateien. Andererseits bieten Storyboards gegenüber XIB-Dateien einige Vorteile, wie Übergänge, statische Tableviews und Prototypen in Table- und Collectionviews; es kann deshalb sinnvoll sein, alte Projekte auf Storyboards zu migrieren.

Dieser Abschnitt zeigt Ihnen, wie Sie eine ältere Version der Wecker-App von XIB-Dateien auf ein Storyboard umstellen. Dabei dient dieses Beispiel auch dazu, dass Sie die Funktionsweise sowohl von Storyboards als auch von XIB-Dateien besser verstehen.

Projektinformation

Den Quellcode für das Ausgangsprojekt finden Sie auf der DVD unter Code/Apps/iOS4/AlarmClock oder im Github-Repository zum Buch im Unterverzeichnis https://github.com/Cocoaneheads/iPhone/tree/Auflage_3/Apps/iOS4/AlarmClock.

Das fertige Projekt mit Storyboard und den Erweiterungen finden Sie auf der DVD unter Code/Apps/iOS6/ExtendedAlarmClock oder im Git im Unterverzeichnis https://github.com/Cocoaneheads/iPhone/tree/Auflage_3/Apps/iOS6/ExtendedAlarmClock.

Zur Vorbereitung kopieren Sie das iOS-4-Beispielprojekt AlarmClock (siehe Kasten) und öffnen diese Kopie in Xcode. Als Erstes legen Sie über FileNewNew File... eine Storyboard-Datei an, indem Sie unter der Rubrik iOSUser Interface die Vorlage Storyboard auswählen (siehe Abbildung 4.4) und die neue Datei unter dem Namen AlarmClock abspeichern. Dieses Storyboard ersetzt alle XIB-Dateien für das iPhone. Sie erstellen zuerst das Storyboard für die englische iPhone-App und leiten später davon die iPad-Variante und lokalisierten Versionen ab.

Abbildung

Abbildung 4.4 Anlegen eines neuen Storyboards

Von den Grundobjekten müssen Sie nur den Viewcontroller im Storyboard anlegen und seinen View in das Storyboard kopieren. Wie Sie Tabelle 4.1 entnehmen können, erzeugt die Funktion UIApplicationMain das Application-Delegate, und die Applikation erzeugt das Applikationsfenster. Sie brauchen sich also nicht um die Erstellung der beiden anderen Objekte zu kümmern.

Storyboards und das Applikationsfenster

Wenn Sie ein Storyboard verwenden, muss das Application-Delegate die Property window implementieren. Die Applikation ruft den Getter dieser Property vor dem Aufruf der Methode application:didFinishLaunchingWithOptions: auf. Wenn er nil zurückliefert, erzeugt die Applikation ein Fenster und weist es über den Setter zu. Liefert die Property hingegen eine Referenz auf ein Fenster zurück, verwendet die Applikation dieses Objekt und legt kein neues an.

Als Erstes legen Sie den Viewcontroller an, indem Sie ein Viewcontroller-Objekt aus der Bibliothek auf die Zeichenfläche ziehen. Danach öffnen Sie den Identitätsinspektor des neuen Viewcontrollers und wählen AlarmClockViewController als Klasse des Objekts aus. Da Sie die View-Hierarchie aus der XIB-Datei übernehmen, müssen Sie zuerst das Viewobjekt löschen, das Xcode beim Anlegen des Viewcontrollers erstellt hat. Dazu klicken Sie einfach in den Viewcontroller auf der Zeichenfläche, so dass er keinen blauen Rand hat, und drücken ___æ oder delete. Dadurch löschen Sie den View, und der Inhalt Ihres Storyboards sollte nun wie in Abbildung 4.5 aussehen – der Viewcontroller in der linken Spalte hat keine Unterobjekte).

Der Viewcontroller sollte der initiale Viewcontroller des Storyboards sein, was Sie wie in Abbildung 4.5 an dem Pfeil auf der linken Seite des Viewcontrollers erkennen. Die App sucht beim Start nach diesem Viewcontroller und zeigt dessen View im Applikationsfenster an. Falls dieser Pfeil in Ihrem Storyboard fehlt, können Sie das über das Feld Initial Scene im Identitätsinspektor des Viewcontrollers ändern, indem Sie den Haken vor Is Initial View Controller setzen.

Kopieren will gelernt sein

Vielleicht wundern Sie sich, warum Sie nicht auch den Controller aus der XIB-Datei in das Storyboard kopieren sollen. Das ist zwar auch möglich, hat allerdings den unschönen Nebeneffekt, dass Xcode auch Eigenschaften mitkopiert, mit denen das Storyboard nichts anfangen kann. Dazu gehört beispielsweise der Name der XIB-Datei. Diese Einstellung führt im schlimmsten Fall zu einem Laufzeitfehler. Leider können Sie den Dateinamen im Storyboard nicht mehr löschen. Aus diesem Grund ist es besser, den Viewcontroller neu anzulegen.

Abbildung

Abbildung 4.5 Das Storyboard nach dem Einfügen des Viewcontrollers

Als Nächstes kopieren Sie den View aus der Datei AlarmClockViewController.xib in das Storyboard, indem Sie in der englischen XIB-Datei das oberste Viewobjekt auswählen und cmd+C drücken. Wechseln Sie danach wieder in das Storyboard, und klicken Sie in den Viewcontroller auf der Zeichenfläche, so dass er einen blauen Rahmen hat. Wenn Sie nun cmd+V drücken, fügt Xcode den View in den Controller ein. Ihr View sollte dann so wie in Abbildung 4.6 aussehen.

Außerdem müssen Sie den Long-Press-Gesture-Recognizer anlegen, indem Sie das entsprechende Objekt aus der Bibliothek auf das Objekt Clock View in der linken Seitenleiste des Interface Builders ziehen.

Abbildung

Abbildung 4.6 Viewcontroller mit View im Storyboard

Die Outlet- und die Action-Verbindungen zwischen Viewcontroller und View müssen Sie neu anlegen. Tabelle 4.2 enthält zu den Views alle Outlet- und Action-Verbindungen des Viewcontrollers, die Sie anlegen müssen. Dabei entsprechen die Namen der Views in der ersten Spalte den Bezeichnungen in Abbildung 4.6.

Tabelle 4.2 Outlet- und Action-Verbindungen des Weckers

View Outlet-Property Action Sent Event

Clock View

clockView

Clock Control

clockControl

updateAlarm

Touch Up Inside

updateTimeLabel

Value Changed

LabelLabel

timeLabel

Long Press Gesture Recognizer

switchAlarm:

Zur Kontrolle können Sie die Outlet- und Action-Verbindungen des Viewcontrollers anhand von Abbildung 4.7 überprüfen.

Abbildung

Abbildung 4.7 Die Verbindungen des Viewcontrollers im Storyboard

Xcode zeigt Ihnen außerdem einen Fehler an, den Sie sehen, wenn Sie den Issue-Navigator über cmd+4 öffnen; es ist die Meldung »Auto Layout on iOS Versions prior to 6.0«, die daher rührt, dass das Deployment-Target des Projekts noch auf iOS 4.3 steht. Um diesen Fehler zu beheben, öffnen Sie den Reiter General in den Projekteinstellungen und setzen das Deployment-Target auf 6.0.

Abbildung

Abbildung 4.8 Deployment-Target umstellen

In der Datei main.m müssen Sie der Funktion UIApplicationMain noch die Klasse des Application-Delegates mitteilen. Die notwendigen Änderungen dafür sehen Sie in Listing 4.5.

#import <UIKit/UIKit.h>
#import "AlarmClockAppDelegate.h"

int main(int argc, char *argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil,
NSStringFromClass([AlarmClockAppDelegate class]));
}
}

Listing 4.5 Erzeugung des App-Delegates über Programmcode

Da das Application-Delegate in einer storyboardbasierten App auch nicht mehr den initialen Viewcontroller an das Applikationsfenster übergeben muss, können Sie die Deklaration der Propertys window und viewController aus der Datei AlarmClockAppDelegate.h entfernen. In der Datei AlarmClockAppDelegate.m löschen Sie außerdem die dazugehörenden @synthesize-Anweisungen sowie alle Anweisungen bis auf return YES; aus der Methode application:didFinishLaunchingWithOptions:. Der Anfang des Implementierungsblocks sollte danach wie in Listing 4.6 aussehen.

@implementation AlarmClockAppDelegate

@synthesize soundId = _soundId;

- (void)dealloc {
self.soundId = nil;
}

- (BOOL)application:(UIApplication *)inApplication
didFinishLaunchingWithOptions:(NSDictionary *)inOptions {
return YES;
}

Listing 4.6 Änderungen am Application-Delegate für das Storyboard

Damit haben Sie die Migration des Views in das Storyboard für das iPhone abgeschlossen. Allerdings verwendet die App das Storyboard noch nicht, weil ihre Einstellungen nach wie vor auf die XIB-Dateien verweisen. Sie können das überprüfen, indem Sie folgende Schritte ausführen:

  1. Löschen Sie die XIB-Dateien für die iPhone-Gerätefamilie aus dem Projekt. Dabei wählen Sie in der Alertbox den Button Move to Trash und nicht Remove References Only.
  2. Entfernen Sie die App vom Gerät beziehungsweise aus dem Simulator, indem Sie den Home-Button gedrückt halten, bis die Symbole zu wackeln anfangen. Durch Drücken der Löschmarke am Icon der App entfernen Sie diese aus dem Simulator.
  3. Löschen Sie alle Zwischendateien des Projekts, indem Sie den Menüpunkt ProductClean aufrufen.

Wenn Sie danach die App erstellen und ausführen, zeigt Ihnen die Debugger-Konsole folgende Meldung an:

2013-08-11 19:57:24.079 AlarmClock[28130:a0b] *** Terminating app due to 
uncaught exception 'NSInternalInconsistencyException', reason: 'Could not
load NIB in bundle: 'NSBundle </Users/clemens/Library/Application Support/
iPhone Simulator/7.0/Applications/79886B42-C0D4-4C2A-812C-2DC0856D179A/
AlarmClock.app> (loaded)' with name 'MainWindow''

Die App versucht also nach wie vor, ihre Views über MainWindow.nib zu laden. Das können Sie über den Reiter General in den Target-Einstellungen ändern. Die Einstellungen bei Main Interface legen das Haupt-Storyboard beziehungsweise die Haupt-XIB-Datei des Targets fest. Um die App zur Verwendung des Storyboards zu bewegen, wählen Sie hier den Eintrag AlarmClock aus (siehe Abbildung 4.9).

Abbildung

Abbildung 4.9 Wechsel von XIB-Dateien zu einem Storyboard

Mit diesen Änderungen haben Sie die Migration auf ein Storyboard für das iPhone abgeschlossen. Um den Viewcontroller in einem Storyboard für das iPad anzulegen, durchlaufen Sie entweder die ganzen Schritte vom Anfang dieses Abschnitts noch einmal mit der Datei AlarmClockViewController-iPad.xib. oder Sie kopieren den Viewcontroller mit dem Gesture-Recognizer aus dem iPhone-Storyboard in das iPad-Storyboard und passen den View entsprechend an. Wenn Sie beide Objekte in einem Schritt kopieren, bleiben auch die Verbindungen zwischen diesen beiden Objekten erhalten.

Das iPad-Storyboard sollte dabei natürlich einen anderen Namen (z. B. AlarmClock-iPad.storyboard) als das iPhone-Storyboard erhalten, und der Clockview und das Clock-Control sollten dabei eine quadratische Fläche (768 × 768) bekommen, um eine schöne Darstellung zu erhalten. Achten Sie auch auf die Koordinaten des Labels; sein y-Wert sollte mindestens 768 sein, damit das Label sich nicht mit dem Clockview überlagert.

Damit die App auf dem iPad auch das entsprechende Storyboard verwendet, öffnen Sie wieder die Target-Einstellungen und scrollen die Ansicht nach unten, bis Sie den Bereich iPad Deployment Info sehen. Auch dort finden Sie zwei Einstellungen: Main Storyboard und Main Interface. Wählen Sie hier unter Main Storyboard den Wert AlarmClock-iPad aus.

Die Umstellung eines Projekts von XIB-Dateien auf Storyboards ist schon für so ein kleines Projekt wie den analogen Wecker recht aufwendig. Glücklicherweise müssen Sie das allerdings in der Praxis nur sehr selten durchführen, da es ja nur ältere Projekte betrifft, bei denen Sie Eigenschaften der Storyboards ausnutzen wollen.


Rheinwerk Computing - Zum Seitenanfang

4.1.4Modale DialogeZur nächsten ÜberschriftZur vorigen Überschrift

Wenn Ihre App mehrere View-Hierarchien verwalten soll, müssen Sie auch die Möglichkeit haben, dazwischen zu wechseln. In Kapitel 3, »Sehen und anfassen«, haben Sie im Zusammenhang mit Übergängen bereits eine Möglichkeit dafür kennengelernt. Ein Übergang führt den Viewwechsel allerdings nicht durch, sondern stößt ihn nur an. Apple hat Übergänge mit Storyboards in iOS 5 eingeführt. Dieser und die folgenden Abschnitte beschreiben, wie Sie Views aus dem Programmcode heraus anzeigen können; Abschnitt 4.1.6 geht dabei auch noch mal genauer auf Übergänge ein.

Modal versus nichtmodal

Ein modaler Dialog sperrt alle anderen Eingabemöglichkeiten einer Applikation. Der Nutzer muss zuerst diesen Dialog bearbeiten, bevor er mit der Applikation weiterarbeiten kann. Typische modale Dialoge unter OS X sind die Dateiauswahlboxen. Ein Beispiel für nichtmodale Dialoge unter OS X sind die Dateiinformationsfenster des Finders.

Auf dem iPhone sperrt ein modaler Dialog alle anderen Eingaben des Viewcontrollers, der den Dialog anzeigt, indem er ihn komplett verdeckt. Das geht auch auf dem iPad; allerdings muss hier nicht den ganzen Bildschirm bedecken, sondern kann auch Teile nur abdunkeln.

Die Klasse UIViewController besitzt für die Anzeige modaler Dialoge die Methode presentViewController:animated:completion:. Über diese Methode können Sie einen Viewcontroller über dem Viewcontroller darstellen, dem Sie diese Nachricht senden. Dabei kann Cocoa Touch die Anzeige animieren, was Sie über den zweiten Parameter vom Typ BOOL steuern können. Außerdem können Sie im dritten Parameter einen Block angeben, den Cocoa Touch nach dem Erscheinen des neuen Views ausführt. Anstelle eines leeren Blocks können Sie hier auch NULL verwenden.

Die Anzeige eines modalen Dialogs läuft in folgenden Schritten ab:

  1. Erzeugung des Viewcontrollers für die Anzeige oder Verwendung eines serialisierten Viewcontrollers aus dem Storyboard
  2. Parameterübergabe an den modalen Viewcontroller
  3. Konfiguration der Anzeigeoptionen
  4. Anzeige des Viewcontrollers

Für den ersten Schritt gibt es unterschiedliche Möglichkeiten. Wenn Sie Ihre Views über XIB-Dateien definieren, können Sie ein neues Objekt für den Viewcontroller anlegen und dabei die XIB-Datei angeben (siehe Listing 4.1). Bei der Verwendung eines Storyboards legen Sie den Viewcontroller darin an und geben ihm über seinen Identitätsinspektor in dem Feld Storyboard ID eine eindeutige Kennung (siehe Abbildung 4.10).

Abbildung

Abbildung 4.10 Kennung für einen Viewcontroller vergeben

Projektinformation

Den Quellcode für dieses Beispielprojekt finden Sie auf der DVD unter Code/Apps/iOS6/Modal oder im Github-Repository zum Buch im Unterverzeichnis https://github.com/Cocoaneheads/iPhone/tree/Auflage_3/Apps/iOS6/Modal.

Von dem Viewcontroller können Sie dann über seine Kennung und die Methode instantiateViewControllerWithIdentifier: aus der Klasse UIStoryboard ein neues Objekt erzeugen. An das Storyboard, aus dem die App den aktuellen Viewcontroller geladen hat, gelangen Sie über die Property storyboard. Eine Action-Methode in einem Viewcontroller kann also einen weiteren Viewcontroller folgendermaßen deserialisieren:

ModalViewController *theController = [self.storyboard 
instantiateViewControllerWithIdentifier:@"modal"];

Listing 4.7 Deserialisierung eines Viewcontrollers aus einem Storyboard

Viewcontroller aus einem Storyboard

Im Unterschied zu NIB-Dateien müssen Sie auch den Viewcontroller immer aus dem Storyboard laden, wenn Sie dessen View dort abgelegt haben. Sie können ihn also nicht über alloc und die Methode init oder initWithNibName:bundle: anlegen und initialisieren. Stattdessen erzeugen Sie die Viewcontroller über die Methode instantiateViewControllerWithIdentifier:.

Nachdem Sie das Viewcontroller-Objekt auf einem der beschriebenen Wege erzeugt haben, können Sie ihm Parameter übergeben. Der neue Viewcontroller soll ja in der Regel mit Daten arbeiten, die er von dem aufrufenden Viewcontroller bekommt. Die Parameterübergabe geschieht am einfachsten über Propertys des modalen Viewcontrollers. Im Beispielprojekt Modal übergibt die Klasse RootViewController eine Zahl an den modalen Dialog. Die Klasse ModalViewController besitzt zu diesem Zweck die Property counter. Die Action-Methode weist nun dieser Property einen Wert zu, bevor sie den Viewcontroller anzeigt (siehe Listing 4.8).

- (IBAction)showModalDialog {
ModalViewController *theController = [self.storyboard
instantiateViewControllerWithIdentifier:@"modal"];

theController.counter = ++self.viewCounter;
theController.modalTransitionStyle =
UIModalTransitionStyleFlipHorizontal;
[self presentViewController:theController animated:YES
completion:^{
NSLog(@"finished");
}];
}

Listing 4.8 Übergabe von Parametern an einen Viewcontroller

Im Beispiel zeigt der modale Viewcontroller den Wert einfach an, indem er in der Methode viewWillAppear: den Wert der Property in eine Zeichenkette umwandelt und an die text-Property eines Labels übergibt.

- (void)viewWillAppear:(BOOL)inAnimated {
[super viewWillAppear:inAnimated];
self.label.text =
[NSString stringWithFormat:@"%d", self.counter];
}

Listing 4.9 Anzeige des Property-Wertes durch ein Label

Direkte Zugriffe auf Views vermeiden

Vielleicht fragen Sie sich, warum die Action-Methode showModalDialog den Titel nicht direkt an das Label übergibt. In Listing 4.8 könnten Sie ja die Outlet-Property für das Label auch öffentlich machen, die Zahl in der Action-Methode in einen Text umwandeln und an theController.label.text übergeben. Das führt in der Regel jedoch zu einem Fehler, da Sie bei der ersten Zuweisung in der Action-Methode zwar das Viewcontroller-Objekt haben; das jedoch noch nicht seinen View geladen haben muss. In diesem Fall ist das label-Outlet gleich nil, und die Zuweisung geht ins Leere.

Die Verwaltung der Views obliegt dem zugehörigen Viewcontroller, der die Views lädt, konfiguriert und zerstört. Er legt fest, wie seine Views die Daten darstellen. Je stärker Sie seinen View nach außen abkapseln, umso leichter können Sie den Aufbau des Views ändern, ohne die restliche App anpassen zu müssen.

Listing 4.9 weist außerdem der Property modalTransitionStyle einen Wert zu. Über diese Property können Sie die Animation für das Erscheinen und Verschwinden des modalen Views festlegen. Die Animation für das Verschwinden ist dabei jeweils entgegengesetzt zu der Animation für das Erscheinen. Es gibt folgende Auswahlmöglichkeiten:

  • UIModalTransitionStyleCoverVertical schiebt den Viewcontroller von unten nach oben in den Bildschirm. Das ist die Standardanimation.
  • UIModalTransitionStyleFlipHorizontal dreht die Views an der zentralen vertikalen Achse umeinander, wie Sie es vielleicht von den Einstellungsdialogen einiger Dashboard-Widgets unter OS X kennen.
  • UIModalTransitionStyleCrossDissolve blendet den aktuellen View aus und gleichzeitig den modalen View durch einen Überblendeffekt ein.
  • UIModalTransitionStylePartialCurl rollt den aktuellen View wie das oberste Blatt eines Kalenders nach oben. Der obere Teil des modalen Views bleibt dabei teilweise verdeckt.

Ein modaler Viewcontroller kann über die Property presentingViewController auf den Viewcontroller zugreifen, der ihn anzeigt.

Abhängigkeiten vermeiden

Durch den Zugriff auf den präsentierenden Viewcontroller erzeugen Sie in der Regel eine Abhängigkeit vom modalen Dialog zu diesem Viewcontroller. Das bedeutet dann meistens, dass Sie den modalen Viewcontroller nur von diesem Viewcontroller aus anzeigen können. Wenn Sie also den modalen Dialog über einen anderen Viewcontroller anzeigen lassen wollen, kann das zu Komplikationen oder weiteren Abhängigkeiten führen. Das endet dann meist in sehr unschönen Fallunterscheidungen und langen Methoden.

Erstellen Sie stattdessen zu der Klasse des modalen Dialogs lieber ein Delegateprotokoll, und fügen Sie der Klasse eine entsprechende Property für das Delegate hinzu. Der modale Dialog ruft dann die Delegate-Methoden auf und braucht die Klasse des präsentierenden Viewcontrollers nicht zu kennen. Ein sehr schönes Beispiel dafür ist die Klasse UIImagePickerController, die Sie noch im Zusammenhang mit dem Fototagebuch kennenlernen.

Wenn der modale Viewcontroller Werte an den präsentierenden Viewcontroller zurückgeben soll, sollte er ein entsprechendes Delegateprotokoll bereitstellen. Im Beispielprojekt besitzt der modale Viewcontroller einen Slider, dessen Wert er an den präsentierenden Viewcontroller zurückgeben soll. Dazu verwendet er das Delegateprotokoll aus Listing 4.10.

@protocol ModalViewControllerDelegate;

@interface ModalViewController : UIViewController

@property (nonatomic) NSUInteger counter;
@property (nonatomic, assign) id<ModalViewControllerDelegate>
delegate;

@end

@protocol ModalViewControllerDelegate <NSObject>

@optional
- (void)modalViewController:

(ModalViewController *)inController
didUpdateValue:(CGFloat)inValue;

@end


Listing 4.10 Protokolldeklaration für den modalen Viewcontroller

Die Klasse ModalViewController sendet in der Methode viewWillDisappear: die Nachricht modalViewController:didUpdateValue: an das Delegate. Da die Implementierung dieser Methode jedoch optional ist, muss die Methode viewWillDisappear: vor dem Versand über @respondsToSelector: prüfen, ob die Delegate-Methode auch vorhanden ist (siehe Listing 4.11).

- (void)viewWillDisappear:(BOOL)inAnimated {
if([self.delegate respondsToSelector:
@selector(modalViewController:didUpdateValue:)]) {
[self.delegate modalViewController:self
didUpdateValue:self.slider.value];
}
[super viewWillDisappear:inAnimated];
}

Listing 4.11 Benachrichtigung des Delegates über die Änderung des Wertes

Die Klasse des Delegates, im Beispielprojekt also die Klasse RootViewController, kann nun die Delegate-Methode implementieren und den übergebenen Wert verarbeiten. Im Beispielprojekt wandelt sie den Wert in eine Zeichenkette um und zeigt ihn über ein Label an:

- (void)modalViewController:(ModalViewController *) 
inController didUpdateValue:(CGFloat)inValue {
self.label.text = [NSString stringWithFormat:@"%.1f",
inValue];
}

Listing 4.12 Implementierung der Delegate-Methode

Damit die Delegation auch funktioniert, muss der Rootviewcontroller vor der Anzeige des modalen Viewcontrollers sich dort noch über die Anweisung theController.delegate = self; als Delegate anmelden.

Die Delegation erfordert zwar ein paar Code-Zeilen mehr, sie bietet gegenüber einem direkten Zugriff auf den präsentierenden Viewcontroller einige Vorteile:

  1. Sei vermeidet eine Abhängigkeit des modalen Viewcontrollers vom präsentierenden Viewcontroller. Dabei setzt sogar die Klasse ModalViewController im Beispielprojekt noch nicht einmal voraus, dass die App sie modal anzeigt, und tatsächlich ist die Delegation ein sehr häufig eingesetztes Mittel für die Kommunikation zwischen zwei Viewcontrollern.
  2. Die Delegation erhöht die Wiederverwendbarkeit des modalen Viewcontrollers: Häufig benötigt eine App ihre modalen Dialoge an mehreren Stellen; denken Sie hier beispielsweise an einen Login-Dialog, den die App immer dann anzeigt, wenn der Nutzer auf geschützte Bereiche in der App zugreifen möchte.
  3. Die Delegation erlaubt nahezu beliebige Objekte für die Auswertung des modalen Dialogs. Im Beispielprojekt ließe sich beispielsweise auch ohne große Mühe das Application-Delegate als Delegate des modalen Viewcontrollers verwenden.

Rheinwerk Computing - Zum Seitenanfang

4.1.5Pop-overZur nächsten ÜberschriftZur vorigen Überschrift

Auf dem iPad sind modale Dialoge, die den kompletten Bildschirm belegen, nicht immer sinnvoll. Häufig brauchen Dialoge nur eine wesentlich kleinere Fläche, als der Bildschirm des iPads bietet, da bei der großen Bildfläche komplette Viewwechsel sehr unruhig wirken können. Stattdessen können Sie auf dem iPad auch ein Pop-over verwenden. Es stellt vor dem ausgegrauten View des präsentierenden Viewcontrollers den Dialog mit einer Pfeilspitze dar (siehe Abbildung 4.11).

Abbildung

Abbildung 4.11 Anzeige eines Dialogs in einem Pop-over

Die Pfeilspitze zeigt in der Regel auf das Element, den Anker, über das Sie das Pop-over geöffnet haben. Im Gegensatz zu modalen Viewcontrollern ist häufig kein Button zum Schließen notwendig, da Cocoa Touch das Pop-over wieder schließt, wenn Sie den Bildschirm außerhalb des Pop-overs berühren. Dieses Verhalten können Sie jedoch verhindern, indem Sie die Property modalInPopover auf YES setzen. Die Logik für die Anzeige von Pop-overn kapselt die Klasse UIPopoverController, die jedoch keine Unterklasse von UIViewController ist.

Für die Anzeige des Pop-overs gibt es zwei Möglichkeiten. Entweder geben Sie einen Button aus der Navigations- oder der Werkzeugleiste an, auf den die Spitze des Popovers zeigen soll. Dafür verwenden Sie die Methode presentPopoverFromBarButtonItem:permittedArrowDirections:animated: der Klasse UIPopoverController. Dabei ist der erste Parameter ein Button aus einer Navigations- oder Werkzeugleiste. Auf diese Leisten geht Abschnitt 4.2, »Der Navigationcontroller«, noch genauer ein. Oder Sie öffnen das Pop-over mit der Methode presentPopoverFromRect:inView:permittedArrowDirections:animated: über einem beliebigen View, den Sie als zweiten Parameter angeben. Mit dem Rechteck im ersten Parameter können Sie die Fläche für die Spitze im View genauer eingrenzen; dabei liegen die Koordinaten des Rechtecks relativ zum View, den Sie im Parameter inView angeben. Im einfachsten Fall verwenden Sie dafür die Bounds des Views. Das Beispielprojekt Modal öffnet auf einem iPad den modalen Dialog in einem Pop-over:

- (IBAction)showPopoverDialog:(id)inSender {
ModalViewController *theController = [self.storyboard
instantiateViewControllerWithIdentifier:@"modal"];

self.popover = [[UIPopoverController alloc]
initWithContentViewController:theController];
theController.counter = ++self.viewCounter;
theController.delegate = self;
[self.popover presentPopoverFromRect:[inSender bounds]
inView:inSender
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}

Listing 4.13 Öffnen eines Pop-overs

Bei der Anzeige eines Pop-overs ist es wichtig, dass eine Referenz den Pop-over-Controller hält; andernfalls stürzt die App mit folgender Fehlermeldung ab:

*** Terminating app due to uncaught exception 'NSGenericException', reason: 
'-[UIPopoverController dealloc] reached while popover is still visible.'

Ein Pop-over braucht Halt

Sie müssen nach der Anzeige eine haltende Referenz auf den Pop-over-Controller besitzen, da das Betriebssystem diesen Controller nicht hält. Aus diesem Grund weist Listing 4.13 den Controller auch der Property popover zu. In der Regel brauchen Sie diese Referenz auch, wenn Sie das Pop-over aus dem Programmcode heraus wieder schließen wollen. Dazu verwenden Sie die Methode dismissPopoverAnimated:.

Beim Öffnen des Pop-overs geben Sie über den Parameter permittedArrowDirections: die möglichen Richtungen der Spitze an. Sie sollten für die Ausrichtung immer sinnvolle Werte verwenden. Andernfalls kann Cocoa Touch das Pop-over schon mal an einer ungewöhnlichen Stelle positionieren. Am einfachsten verwenden Sie die Konstante UIPopoverArrowDirectionAny; dann wählt iOS automatisch eine geeignete Ausrichtung.

Die Größe des Pop-over-Controllers lässt sich über die Felder unter Popover im Attributinspektor des Viewcontrollers festlegen. Dazu müssen Sie die Option Use Explicit Size setzen und in die darunterliegenden Felder die gewünschte Größe eintragen. Allerdings ändern Sie damit nicht die Größe des Views im Interface Builder beziehungsweise Storyboard. Diese Größe hat zwar keine Auswirkung auf die App; dennoch ist es natürlich für die Erstellung des Views im Interface Builder sehr hilfreich, wenn der View im Interface Builder die gleiche Größe wie in der App hat.

Für die Größenänderung stellen Sie im Attributinspektor des modalen Viewcontrollers in der Rubrik Simulated Metrics im Feld Size den Wert Freeform ein. Durch diese Einstellung können Sie die Größe des Views des Controllers über den Größeninspektor des Views beliebig ändern, wodurch der View im Storyboard auch seine Größe ändert. Die Einstellungen des Attributinspektors für den Viewcontroller stellt Abbildung 4.12 dar.

Abbildung

Abbildung 4.12 Attribute für einen Viewcontroller im Pop-over-Controller


Rheinwerk Computing - Zum Seitenanfang

4.1.6ÜbergängeZur nächsten ÜberschriftZur vorigen Überschrift

In einem Storyboard können Sie modale Dialoge natürlich wesentlich einfacher durch Übergänge öffnen, da ja in der Regel das Storyboard alle Viewcontroller der App enthält. Durch Übergänge können Sie jeweils ein Control [Anm.: Cocoa Touch und der Interface Builder unterstützen hier allerdings nur echte Unterklassen von UIControl aus dem UIKit; für selbsterstellte Controls gilt: Wir müssen leider draußen bleiben.] , einen anderen Button aus dem UIKit oder einen Viewcontroller mit einem Viewcontroller verbinden. Wie Sie Übergänge mit dem Interface Builder anlegen und wie Sie damit einen modalen Dialog öffnen, haben Sie bereits in Kapitel 3 erfahren: Sie ziehen eine Verbindung von einem beliebigen Control oder einem Viewcontroller zu einem Viewcontroller und wählen den gewünschten Übergangstyp aus.

Tabelle 4.3 enthält eine Liste mit allen Übergangstypen und den Gerätegruppen, die sie unterstützen. Da es beispielsweise Pop-over-Controller und Splitviews nur auf dem iPad gibt, ist natürlich auch nur dort der entsprechende Übergang sinnvoll.

Tabelle 4.3 Die verschiedenen Arten von Übergängen

Typ Gerätegruppe Version Übergang

Custom

alle

iOS 5

Erlaubt die Implementierung beliebiger Übergänge.

Modal

Zeigt den View des Viewcontrollers als modalen Dialog an.

Push

Schiebt den Viewcontroller auf den Stack des Navigationcontrollers.

Pop-over

iPad

Anzeige des Viewcontrollers in einem Pop-over

Replace

Wechselt den rechten Viewcontroller (Detailviewcontroller) in einem Splitview aus.

Unwind

alle

iOS 6

Springt in einer Navigationshierarchie zurück zu einem übergeordnetem Viewcontroller; er ist das Gegenstück zu Push.

Embed

Bettet den View eines Viewcontrollers in den View eines anderen ein. Diesen Übergang legen Sie über einen speziellen View und nicht über eine Verbindung an.

Über den Typ Custom können Sie auch eigene Übergänge erstellen. Sie müssen dafür eine Unterklasse von UIStoryboardSegue schreiben und die Methode perform implementieren. Cocoa Touch ruft diese Methode auf, um den Zielviewcontroller des Übergangs anzuzeigen. In Abschnitt 4.7.1, »Container- und Subviewcontroller«, finden Sie Beispiele für die Übergangstypen Custom sowie Embed, und Abschnitt 4.2.4, »Gehe drei Felder zurück«, zeigt Ihnen die Verwendung des Typs Unwind.

Benannte Übergänge

Wie eingangs in diesem Abschnitt erwähnt, können Sie im Storyboard auch Übergänge zwischen zwei Viewcontrollern festlegen. Einen solchen Übergang löst die App allerdings nicht direkt durch das Berühren eines Controls aus, sondern sie kann den Übergang dann nur explizit über eine Methode anstoßen. Dazu müssen Sie dem Übergang in dessen Attributinspektor zunächst eine Kennung geben (siehe Abbildung 4.13).

Abbildung

Abbildung 4.13 Kennung eines Übergangs festlegen

Über die Kennung und die Methode performSegueWithIdentifier:sender: des Quellviewcontrollers lösen Sie nun den Übergang aus. Das geschieht im Beispielprojekt Modal in der Action-Methode triggerDialogSegue:

- (IBAction)triggerDialogSegue:(id)inSender {
[self performSegueWithIdentifier:@"dialog"
sender:inSender];
}

Listing 4.14 Auslösen eines Übergangs

Diese Action-Methode verwendet das Projekt sowohl für die iPhone- als auch für die iPad-Version. Dabei ist der Übergang »dialog« im iPhone-Storyboard modal, während er im Storyboard für das iPad ein Pop-over anzeigt.

Pop-over-Übergänge müssen immer auf einen View als Anker verweisen. Wenn Sie den Übergang von einem Control zu einem Viewcontroller ziehen, verwendet der Interface Builder automatisch das Control als Anker. Bei Übergängen zwischen zwei Viewcontrollern müssen Sie den Anker jedoch manuell festlegen, um nicht folgenden Laufzeitfehler zu erhalten:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyExcep-
tion', reason: 'UIStoryboardPopoverSegue must be presented from a bar button item or a
view.'

Über den Attributinspektor des Übergangs können Sie über das Feld Anchor den Anker festlegen oder auch ändern, indem Sie aus dem Kreis auf der rechten Seite des Feldes ein Gummiband zu dem gewünschten View ziehen, der als Anker dienen soll (siehe Abbildung 4.14).

Abbildung

Abbildung 4.14 Anker für Pop-over-Übergang festlegen



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.

>> Zum Feedback-Formular
<< zurück




Copyright © Rheinwerk Verlag GmbH, Bonn 2014
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de


  Zum Katalog
Zum Katalog: Apps programmieren für iPhone und iPad






Neuauflage: Apps programmieren für iPhone und iPad
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Einstieg in Objective-C 2.0 und Cocoa






Einstieg in Objective-C 2.0 und Cocoa


Zum Katalog: Spieleprogrammierung mit Android Studio






Spieleprogrammierung mit Android Studio


Zum Katalog: Android 5






Android 5


Zum Katalog: iPhone und iPad-Apps entwickeln






iPhone und iPad-Apps entwickeln


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo