Datentypen und Optionals

Werbung
Holger Hinzberg
iOS-Apps mit Swift 2
Das umfassende Praxis-Handbuch
Bibliografische Information der Deutschen Nationalbibliothek
Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über <http://dnb.d-nb.de>
abrufbar.
ISBN 978-3-95845-222-0
1. Auflage 2016
www.mitp.de
E-Mail: [email protected]
Telefon: +49 7953 / 7189 - 079
Telefax: +49 7953 / 7189 - 082
© 2016 mitp Verlags GmbH & Co. KG, Frechen
Dieses Werk, einschließlich aller seiner Teile, ist urheberrechtlich geschützt. Jede Verwertung außerhalb der engen Grenzen des Urheberrechtsgesetzes ist ohne Zustimmung des
Verlages unzulässig und strafbar. Dies gilt insbesondere für Vervielfältigungen, Übersetzungen, Mikroverfilmungen und die Einspeicherung und Verarbeitung in elektronischen
Systemen.
Die Wiedergabe von Gebrauchsnamen, Handelsnamen, Warenbezeichnungen usw. in diesem Werk berechtigt auch ohne besondere Kennzeichnung nicht zu der Annahme, dass solche Namen im Sinne der Warenzeichen- und Markenschutz-Gesetzgebung als frei zu
betrachten wären und daher von jedermann benutzt werden dürften.
Lektorat: Sabine Schulz
Sprachkorrektorat: Petra Heubach-Erdmann
Coverbild: © Max Krasnov @fotolia.de
Satz: III-satz, Husby, www.drei-satz.de
Referenzkarte
Swift 2
Variablen und Konstanten
Schleifen
// Variablen und Konstanten
var variableValue = 3.1415
variableValue = 3.0
for var index = 0; index <= 5; index++
{
print(index) // Ausgabe von 0 bis 5
}
let constValue = 42
// Neue Zuweisung nicht möglich
// constValue = 50
Fallunterscheidungen
var salary = 10000
if salary > 15000
{
print("Zu viel")
}
else if salary < 10000
{
print("Zu wenig")
}
else
{
print("Ok")
}
var index = 4
switch index
{
case 1:
print("Index
case 2:
print("Index
case 3...5:
print("Index
case 6:
print("Index
fallthrough
default:
print("Index
}
for index in 0...5 // Closed Range
{
print(index) // Ausgabe von 0 bis 5
}
for index in 0..<5 // Half-Open Range
{
print(index) // Ausgabe von 0 bis 4
}
for index in (5...10).reverse()
{
print(index) // Ausgabe von 10 bis 5
}
var access = 1
repeat
{
print(access) // Ausgabe von 1 bis 9
access++
}
while access < 10
ist 1")
ist 2")
liegt zwischen 3 und 5")
ist 6")
liegt nicht zwischen 1 bis 5")
Referenzkarte zum Buch »iOS-Apps mit Swift 2« von Holger Hinzberg, ISBN 978-3-95845-221-3,
www.mitp.de/221, mitp-Verlag
Referenzkarte
Swift 2
Array
var cities:[String] = ["Rom","Paris","Berlin"]
cities.append("London")
for city in cities
{
print(city) // Ausgabe aller Städtenamen
}
var count = cities.count // Anzahl der Elemente
Methoden/Funktionen
// Ohne Parameter und ohne Rückgabewert
func doSomething()
{
print("Hello World!")
}
doSomething()
// Mit einem Double als Parameter und einem Double
// als Rückgabewert
func doSomething(value:Double) -> Double
{
return value * 2.0
}
var twice = doSomething(4.5)
// Mit zwei benannten Parametern
// und einem Double als Rückgabewert
func doSomething(
firstValue first:Double, secondValue second:Double) -> Double
{
return first + second
}
var sum = doSomething(firstValue: 3.2, secondValue: 4.7)
Referenzkarte zum Buch »iOS-Apps mit Swift 2« von Holger Hinzberg, ISBN 978-3-95845-221-3,
www.mitp.de/221, mitp-Verlag
Referenzkarte
Swift 2
Dictionary
var animals:[Int: String] = [11:"Hund", 22:"Katze", 33:"Maus"]
animals[22] = "Elefant" // Element ersetzen
animals[99] = "Huhn" // Element anfügen
print(animals[22]) // Ausgabe "Optional (Elefant)"
print(animals[99]) // Ausgabe "Optional (Huhn)"
animals[11] = nil // Element entfernen
Zeichenketten
var firstName = "Mike"
var lastName = "Müller"
// String-Interpolation
print("Mein Name ist \(firstName) \(lastName).")
// Zahlenwerte formatieren
var numeric = 3.34983632
var num = String(format:"%.2f", numeric) // Ausgabe 3.35
Klassen
class Person
{
// Eigenschaften
var firstName:String
var lastName:String
init()
{
// Eigenschaften initialisieren
firstName = ""
lastName = ""
}
}
// Klasseninstanz erzeugen und
// Eigenschaften zuweisen
var pers = Person()
pers.firstName = "Mike"
pers.lastName = "Müller"
Enumerationen
enum Color
{
case Red
case Green
case Blue
}
var exterior:Color = Color.Green
Referenzkarte zum Buch »iOS-Apps mit Swift 2« von Holger Hinzberg, ISBN 978-3-95845-221-3,
www.mitp.de/221, mitp-Verlag
Referenzkarte
Swift 2
Fehlerbehandlung mit try-catch
// Eigene Fehlertypen definieren
enum CalculationError : ErrorType
{
case DivideByZero
case OtherError
}
// Funktion kann einen Fehler zurückgeben
func divide(dividend:Int, divisor:Int) throws -> Int
{
guard divisor > 0 else
{
throw CalculationError.DivideByZero
}
return dividend / divisor
}
// Funktionsaufruf und Fehlerbehandlung
do
{
var result = try divide(100, divisor: 0)
}
catch(CalculationError.DivideByZero)
{
print("Es wurde versucht, durch null zu teilen")
}
catch
{
print("Ein anderer Fehler ist aufgetreten")
}
Referenzkarte zum Buch »iOS-Apps mit Swift 2« von Holger Hinzberg, ISBN 978-3-95845-221-3,
www.mitp.de/221, mitp-Verlag
Inhaltsverzeichnis
Danksagung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13
Einleitung. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
An wen richtet sich das Buch? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Aufbau des Buches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Teil I: Grundlagen der Sprache Swift . . . . . . . . . . . . . . . . . . . . . . . . . .
Teil II: iOS-Apps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Swift ist nicht Objective-C Version 3.0 . . . . . . . . . . . . . . . . . . . . . . . . .
Kommentare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Stilmittel in den Listings. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die Frameworks der Apple-Plattformen . . . . . . . . . . . . . . . . . . . . . . . .
Die Installation von Xcode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die Entwickler-Community von Apple . . . . . . . . . . . . . . . . . . . . . . . . .
Webseite und Downloads zum Buch. . . . . . . . . . . . . . . . . . . . . . . . . . .
15
15
16
16
18
21
23
24
24
26
28
28
Teil I
Grundlagen der Sprache Swift . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
29
1
1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
Datentypen und Optionals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Willkommen auf dem Spielplatz . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Variablen und Konstanten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Zahlendatentypen konvertieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Werte runden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Minimum und Maximum. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Der Datentyp Bool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Optionals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Programmieren mit Optionals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
31
31
33
38
41
42
43
44
46
2
2.1
2.2
2.3
2.4
Zeichenketten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
String Interpolation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Zeichenketten vergleichen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Textabschnitte finden und ersetzen . . . . . . . . . . . . . . . . . . . . . . . . . . .
Zeichenketten in Zahlentypen konvertieren . . . . . . . . . . . . . . . . . . . .
49
50
52
54
57
5
Inhaltsverzeichnis
6
2.5
2.6
2.7
2.8
Die Klasse NSNumber. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Texte teilen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Subscripting mit Unicode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Anfang und Ende von Zeichenketten. . . . . . . . . . . . . . . . . . . . . . . . . .
60
61
63
65
3
3.1
3.2
3.3
3.4
Arrays und Dictionaries. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Arrays – Listen von Elementen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Arrays sortieren und filtern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Dictionaries, die schnellen Wörterbücher . . . . . . . . . . . . . . . . . . . . . .
Arrays aus Dictionaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
67
67
71
73
77
4
4.1
4.2
4.3
4.4
4.5
4.6
4.7
4.8
4.9
Fallunterscheidungen und Schleifen . . . . . . . . . . . . . . . . . . . . . . . . . .
Die if-Struktur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die switch-case-Struktur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die for-Schleife. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Schleifen und Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Rückwärts durch die for-Schleife . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die while-Schleife . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Schleifen mit Fallunterscheidungen . . . . . . . . . . . . . . . . . . . . . . . . . .
Werte als Diagramme anzeigen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Gültigkeitsbereiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
79
79
85
88
90
91
93
94
97
99
5
5.1
5.2
5.3
5.4
5.5
5.6
5.7
5.8
Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die erste Funktion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Benannte Parameter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Funktionen mit Rückgabewert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Tupel und anonyme Typen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Eine unbestimmte Anzahl von Parametern. . . . . . . . . . . . . . . . . . . . .
Funktionen mit Standardwerten. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Parameter sind unveränderlich. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Aliasse. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
103
103
107
109
111
114
117
119
121
6
6.1
6.2
6.3
6.4
6.5
6.6
6.7
Closures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Closures sind Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Closures als Parameter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Arrays sortieren mit Closures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Variablen einfangen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Asynchrone Closures mit Grand Central Dispatch . . . . . . . . . . . . . . .
Parallele Verarbeitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Asynchrone Aufrufe mittels Completion-Handler . . . . . . . . . . . . . . .
125
125
127
131
135
138
141
143
Inhaltsverzeichnis
7
7.1
7.2
7.3
7.4
7.5
7.6
7.7
Klassen und Objekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Das erste Projekt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Erste Schritte im Workspace-Fenster . . . . . . . . . . . . . . . . . . . . . . . . . .
Die Klasse Person . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Von der Klasse zum Objekt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Eigenschaften und Punktnotation . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Berechnete Eigenschaften mit Getter und Setter . . . . . . . . . . . . . . . .
Eigenschaften beobachten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
147
147
150
153
155
156
157
161
8
8.1
8.2
8.3
8.4
8.5
Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Methoden zur Initialisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Failable Initializers – Wenn es mal schiefgeht . . . . . . . . . . . . . . . . . .
Methoden zu Deinitialisierung. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Klassenmethoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Methoden kontra Eigenschaften. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
167
169
172
174
175
177
9
9.1
9.2
9.3
9.4
9.5
9.6
9.7
Vererbung und Assoziationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Das Erbe der Klasse Person . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Erweiterungen der abgeleiteten Klasse . . . . . . . . . . . . . . . . . . . . . . . .
Methoden überschreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die Initialisierung abgeleiteter Klassen . . . . . . . . . . . . . . . . . . . . . . . .
Assoziationen – Beziehungen zwischen Objekten . . . . . . . . . . . . . . .
Optional Chaining . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Der Coalescin Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
181
181
184
185
187
191
195
198
10
10.1
10.2
10.3
10.4
10.5
Protokolle und Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Ein eigenes Protokoll entwickeln . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Protokolle statt Datentypen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Optionale Protokolle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Extensions mit Protokollen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
199
199
202
204
207
209
11
11.1
11.2
11.3
11.4
11.5
11.6
Strukturen und Enumerationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Zurück zum Spielplatz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Strukturen oder Klassen? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
String Dependencies – Abhängigkeiten von Zeichenketten . . . . . . .
Enumerationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Verschachtelte Enumerationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Enumerationen mit Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
213
213
217
219
220
223
224
7
Inhaltsverzeichnis
8
11.7
11.8
Enumerationen mit begleitenden Werten . . . . . . . . . . . . . . . . . . . . . .
Binärzahlen und OptionSetType-Strukturen. . . . . . . . . . . . . . . . . . . .
226
228
12
12.1
12.2
12.3
12.4
12.5
Sicherer Programmcode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Funktionen absichern mit guard . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
defer-Blöcke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Fehlerbehandlung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Fehler werfen mit throw . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Fehler auffangen mit catch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
235
235
237
239
241
242
13
13.1
13.2
13.3
Speicherverwaltung mit Referenzzähler . . . . . . . . . . . . . . . . . . . . . . .
Automatic Reference Counting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Starke und schwache Referenzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Zirkelverweise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
245
247
248
249
14
14.1
14.2
14.3
14.4
14.5
14.6
14.7
14.8
Robuste Anwendungen und automatisierte Tests . . . . . . . . . . . . . . .
Markup-Kommentare im Playground . . . . . . . . . . . . . . . . . . . . . . . . .
Kommentare in Projekten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Kommentare für die Jumpbar. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Assertions – Die Behauptungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Kompilieren als Debug oder Release . . . . . . . . . . . . . . . . . . . . . . . . . .
Präprozessor-Makros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Automatisiertes Testen mit Xcode . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Tests für eigene Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
251
251
254
257
258
261
264
266
269
Teil II iOS-Apps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
275
15
15.1
15.2
15.3
15.4
15.5
15.6
15.7
15.8
15.9
277
277
279
282
288
289
291
295
298
302
Lotto – 6 aus 49 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
MVC: Model View Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Der iOS-Simulator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Der Lottozahlengenerator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Der Interface Builder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Inspector und Bibliothek. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Arbeiten mit dem Interface Builder . . . . . . . . . . . . . . . . . . . . . . . . . . .
Der Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Zurück zum Interface Builder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Das war es jetzt schon? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Inhaltsverzeichnis
16
16.1
16.2
16.3
16.4
16.5
16.6
16.7
Ein Blick hinter die Kulissen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Was verbirgt sich hinter IBAction und IBOutlet? . . . . . . . . . . . . . . . .
Ein View wird geladen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Programmstart einer iOS-Anwendung . . . . . . . . . . . . . . . . . . . . . . . .
Instanzen erzeugen mit Lazy Loading . . . . . . . . . . . . . . . . . . . . . . . . .
Alles dreht sich . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Erste Schritte mit Autolayout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Ein Icon für die App . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
305
305
307
309
314
315
317
324
17
17.1
17.2
17.3
17.4
17.5
17.6
17.7
Eingaben mit virtuellen Tastaturen . . . . . . . . . . . . . . . . . . . . . . . . . . .
Einsatz für Autolayout. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Auftritt für den Assistenten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Tastaturen ein- und ausblenden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Der First Responder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Navigation zwischen Eingabefeldern . . . . . . . . . . . . . . . . . . . . . . . . . .
Aus dem View in das Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Mitteilungen mit dem UIAlertView . . . . . . . . . . . . . . . . . . . . . . . . . . .
329
331
333
338
341
343
345
347
18
18.1
18.2
18.3
18.4
18.5
Schieberegler, Textformatierungen und unendliche Werte . . . . . . . .
Der Schieberegler – UISlider . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Daten-Model: ConsumptionCalculator . . . . . . . . . . . . . . . . . . . . . . . .
Methodenaufrufe mit Absender . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Statische und dynamische Textformatierungen . . . . . . . . . . . . . . . . .
Ungültige Werte erkennen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
351
352
356
359
363
366
19
19.1
19.2
19.3
19.4
19.5
19.6
19.7
Storyboards – Mit dem Drehbuch durch die App . . . . . . . . . . . . . . . .
Ein einfaches Storyboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Segue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Der Lebenszyklus einer Szene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Storyboards mit Datenübergabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Detailansicht und Navigation Controller . . . . . . . . . . . . . . . . . . . . . . .
Vorbereitungen für den Übergang. . . . . . . . . . . . . . . . . . . . . . . . . . . .
Daten für die View Controller. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
371
371
375
379
381
387
391
393
20
20.1
20.2
20.3
Storyboards mit Protokollen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Ein Protokoll für den View Controller . . . . . . . . . . . . . . . . . . . . . . . . .
Das UIApplicationDelegate-Protokoll . . . . . . . . . . . . . . . . . . . . . . . . .
Eine Szene für das Jahr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
399
400
403
404
9
Inhaltsverzeichnis
10
20.4
20.5
Verpflichtungen für den View Controller . . . . . . . . . . . . . . . . . . . . . .
Kommunikation in alle Richtungen . . . . . . . . . . . . . . . . . . . . . . . . . . .
408
413
21
21.1
21.2
21.3
21.4
21.5
Navigation mit einem Tableisten-Controller . . . . . . . . . . . . . . . . . . . .
Der Tableisten-Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Konfiguration der Schaltflächen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Ausflug in die Delegation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Ein Delegate für den Tableisten-Controller . . . . . . . . . . . . . . . . . . . . .
Delegation – meine Nachrichten an dich. . . . . . . . . . . . . . . . . . . . . . .
415
416
419
423
424
427
22
22.1
22.2
22.3
22.4
22.5
Grafische Oberflächen ohne Interface Builder . . . . . . . . . . . . . . . . . .
Kontrolle ist gut – eine Checkliste ist besser! . . . . . . . . . . . . . . . . . . .
Steuerelemente erstellen mit Swift-Anweisungen . . . . . . . . . . . . . . .
Nachrichten mit Target-Action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Tags – Etiketten für Objekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Suchen im Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
433
434
438
444
447
448
23
23.1
23.2
23.3
23.4
23.5
23.6
23.7
Serialisierung – Aus dem Speicher in eine Datei . . . . . . . . . . . . . . . .
Ein Dictionary für das Repository. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Objekte sortieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Alles nicht ganz so einfach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die Sandbox – Apps im Sandkasten. . . . . . . . . . . . . . . . . . . . . . . . . . .
Das NSCoding-Protokoll . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Serialisierung – Jetzt wird gespeichert! . . . . . . . . . . . . . . . . . . . . . . . .
Die Nachrichtenzentrale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
455
455
458
460
463
464
466
472
24
24.1
24.2
24.3
24.4
24.5
24.6
24.7
Der Picker – ein ganz besonderes Steuerelement. . . . . . . . . . . . . . . .
Eine neue Klasse für Farben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Das Picker-Steuerelement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Protokolle für den Picker. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Kommunikation mit einem Picker. . . . . . . . . . . . . . . . . . . . . . . . . . . .
Eine Farbmischer-App. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Picker-Einstellungen auslesen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Von Dezimal zu Hexadezimal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
477
478
482
484
487
489
492
493
25
25.1
25.2
25.3
25.4
Tabellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die Showroom-App – der digitale Ausstellungsraum . . . . . . . . . . . .
Wohin mit dem Daten-Model? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Konfigurationen im Interface Builder . . . . . . . . . . . . . . . . . . . . . . . . .
Der Tabellen-View-Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
497
498
501
502
506
Inhaltsverzeichnis
25.5
25.6
25.7
25.8
Zweite Szene: Die Detailansicht. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Ein neuer Segue. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Vorsicht, Fehlerquelle! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Bilder anzeigen mit dem UIImageView . . . . . . . . . . . . . . . . . . . . . . .
510
513
517
518
26
26.1
26.2
26.3
26.4
26.5
26.6
26.7
Eye Candy – Unsere App soll schöner werden . . . . . . . . . . . . . . . . . .
Angepasste Tabellenzellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Ein Controller für die Tabellenzelle . . . . . . . . . . . . . . . . . . . . . . . . . . .
Abgerundete Ecken und Rahmen . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Settings – die Einstellungen einer App . . . . . . . . . . . . . . . . . . . . . . . .
NSUserDefaults – die Benutzereinstellungen . . . . . . . . . . . . . . . . . .
Standardeinstellungen erforderlich . . . . . . . . . . . . . . . . . . . . . . . . . . .
Kommunikation mit der Nachrichtenzentrale . . . . . . . . . . . . . . . . . .
525
529
533
536
539
544
546
548
27
27.1
27.2
27.3
27.4
27.5
27.6
Der Collection View. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Storyboard mit Collection View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Der Collection View Controller. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Mit dem Segue zur Detailansicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Teilen mit dem UIActivityViewController. . . . . . . . . . . . . . . . . . . . . .
Drucken mit AirPrint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Unterschiedliche Texte für unterschiedliche Dienste. . . . . . . . . . . . .
553
553
557
563
566
570
572
28
28.1
28.2
28.3
28.4
28.5
28.6
28.7
28.8
Zeichnen mit Core Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die Klasse UIView. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Rechtecke zeichnen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Frame und Bounds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Farbige Formen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Speichern der Context-Einstellungen. . . . . . . . . . . . . . . . . . . . . . . . . .
Zeichnen von Farbverläufen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Arbeiten mit Beschneidungspfaden. . . . . . . . . . . . . . . . . . . . . . . . . . .
Kurven und Figuren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
577
577
581
585
590
593
596
599
603
29
29.1
29.2
29.3
29.4
29.5
29.6
29.7
Multi-Touch mit Gestenerkennung . . . . . . . . . . . . . . . . . . . . . . . . . . .
Linien zeichnen einen Pfeil . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Einfache Berührungserkennung . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Wischgesten erkennen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Objekte bewegen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Pinch to Zoom – Vergrößern mit zwei Fingern . . . . . . . . . . . . . . . . .
Verschiedene Gesten gleichzeitig erkennen . . . . . . . . . . . . . . . . . . . .
Objekte drehen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
609
609
611
613
614
618
622
624
11
Inhaltsverzeichnis
12
29.8
29.9
Gesten im Konflikt. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die Schüttelgeste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
626
628
30
30.1
30.2
30.3
30.4
30.5
30.6
Digitale und analoge Uhren mit Timern . . . . . . . . . . . . . . . . . . . . . . .
Die Klasse NSTimer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Wie spät ist es? – Datum und Uhrzeit ermitteln . . . . . . . . . . . . . . . .
Extensions für die Klasse NSTimer . . . . . . . . . . . . . . . . . . . . . . . . . . .
Eine analoge Uhr mit Core Graphics . . . . . . . . . . . . . . . . . . . . . . . . . .
Ein Zifferblatt zeichnen mit Winkelfunktionen . . . . . . . . . . . . . . . . .
Timer im Einsatz – die Uhr tickt . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
631
631
635
636
641
645
647
31
31.1
31.2
31.3
31.4
Lokale Benachrichtigungen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Lokale Benachrichtigungen mit UILocalNotification . . . . . . . . . . . . .
Eingehende Nachrichten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Benachrichtigungen anpassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Push-Benachrichtigungen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
651
652
656
659
661
32
32.1
32.2
32.3
32.4
32.5
32.6
Karten und Koordinaten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Der Location-Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Auswerten von Positionsinformationen. . . . . . . . . . . . . . . . . . . . . . . .
Geocoding – Wo bin ich hier?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Karten mit dem MKMapView . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Annotations – Anmerkungen auf der Karte . . . . . . . . . . . . . . . . . . . .
Benutzerdefinierte Anmerkungen gestalten und anzeigen . . . . . . . .
663
664
666
669
672
678
681
33
33.1
33.2
33.3
33.4
33.5
33.6
33.7
33.8
Daten suchen und finden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Zugriff mit Key Value Coding. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Schlüsselpfade und Aggregatfunktionen . . . . . . . . . . . . . . . . . . . . . . .
Listen filtern mit NSPredicate. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Erweiterte Vergleiche, logische Operatoren und Closures . . . . . . . . .
Prädikate mit regulären Ausdrücken . . . . . . . . . . . . . . . . . . . . . . . . . .
Daten filtern für Tabellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Listen für den Tabellen-View-Controller . . . . . . . . . . . . . . . . . . . . . . .
Suchen mit dem UISearchController. . . . . . . . . . . . . . . . . . . . . . . . . .
685
685
688
692
695
697
698
703
706
Stichwortverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
715
Danksagung
Die Programmiersprache Swift und die iOS-Entwicklung sind aufregende Technologien und es gibt viele Themen, die ebenfalls ein Kapitel in diesem Buch verdient
hätten. Als Autor habe ich die Erfahrung machen müssen, dass ein Buch nie wirklich fertig ist. Irgendwann muss man allerdings aufhören, zu schreiben, denn die
Mitarbeiter vom Verlag möchten auch ihren Beitrag leisten.
Mein Dank geht an erster Stelle an meine geduldige Lektorin Sabine Schulz, die
mir erneut die Gelegenheit gab, meine Ideen und Erfahrungen in einem Buch zu
veröffentlichen. Ich danke ihr, auch stellvertretend für alle Mitwirkenden in der
Korrektur, im Satz und in der Produktion.
Dank geht an meinen Freund Peter Mekelburg, der seit vielen Jahren bereitwillig
alle meine Texte prüft und mich davor bewahrt, durch zu viele fehlende Satzzeichen und zu komplizierte Sätze unangenehm aufzufallen.
Nicht vergessen darf ich Horst Andreas Roemer, der ebenfalls gerne einen kritischen Blick auf meine Texte wirft. Unsere kreative Zusammenarbeit war wieder
ein Spaß, den wir hoffentlich beim nächsten Buch fortsetzen können.
Mein besonderer Dank geht an alle Leser meiner Bücher, von denen ich einige
inzwischen persönlich auf Konferenzen und Seminaren kennenlernen durfte. Ich
hoffe, wir werden viele weitere Jahre zusammen Spaß haben!
Holger Hinzberg
Holzwickede, März 2016
13
Einleitung
Das iPhone – für viele technikbegeisterte Menschen ist dieser Name gleichbedeutend mit dem modernen Mobiltelefon, das inzwischen leistungsfähiger ist als
die sperrigen Computer, die noch vor einigen Jahren auf vielen Schreibtischen zu
finden waren. Auch Softwareentwickler zieht es seit Jahren zum iPhone. Zu
verlockend ist die iOS-Plattform mit ihren Geräten. Neben leistungsfähigen
Prozessoren verfügen das iPhone und seine Geschwister durch die eingebauten
Sensoren und Kameras über Fähigkeiten, die ein klassischer Rechner nicht bieten
kann. Eine Multi-Touch-Oberfläche, die es erlaubt, Programme direkt auf dem
Bildschirm zu bedienen, bringt bisher unbekannte und aufregende Möglichkeiten. Verständlich ist der Wunsch vieler Programmierer, für diese Plattform zu entwickeln. Ein Einstieg war oft nicht leicht, denn seit über 20 Jahren wurde bei der
Firma aus Kalifornien fast ausschließlich mit Objective-C programmiert – eine
leistungsfähige Programmiersprache, die außerhalb von Apple aber kaum bekannt
war.
Die Abkehr vom Vertrautem erfolgte am 1. Juni 2014, als Apple auf der WWDCKonferenz in San Francisco die Programmiersprache Swift der Öffentlichkeit vorstellte. Für die Zuschauer war das eine Überraschung und bei vielen Entwicklern
die Skepsis groß. Das Erlernen einer Programmiersprache braucht Zeit, und die
ist für viele Programmierer, besonders jene, die mit der Softwareentwicklung
ihren Lebensunterhalt verdienen, gleichbedeutend mit Geld. Dessen ungeachtet
bringt Swift endlich Möglichkeiten für OS-X- und iOS-Projekte, die es in anderen
Programmiersprachen schon seit vielen Jahren gibt. Typsicherheit, Closures und
Optionals waren einige der Schlagwörter, mit denen man während der Präsentation
das Herz der Programmierer schneller schlagen ließ. Ein Jahr später wurde Swift in
der Version 2.0 vorgestellt. Ein untrügliches Zeichen, dass es Apple mit der neuen
Sprache ernst meint. Inzwischen verwenden immer mehr Entwickler die Sprache
Swift für neue Projekte. Verpassen Sie nicht die Gelegenheit, dabei zu sein!
An wen richtet sich das Buch?
Trotz meiner guten Vorsätze, eine wirklich einfache Einführung in die iOS-Entwicklung mit Swift zu schreiben, fängt auch dieses Buch leider nicht bei null an.
Dafür reichen die zur Verfügung stehenden Seiten bedauernswerterweise nicht
aus. Wenn Sie als Leser aber schon ein wenig Erfahrung in einer anderen objektorientierten Programmiersprache haben und jetzt iOS-Apps mit Swift schreiben
15
Einleitung
wollen, sollten die Beispiele für Sie keine großen Hürden sein. Dabei ist es auch
unerheblich, ob Sie Vollzeitentwickler oder nur Hobbyprogrammierer sind. Wenn
Begriffe wie Compiler, Objekte und Vererbung für Sie keine Fremdwörter sind,
dann steht Ihnen der Weg offen, ein erfolgreicher iOS-Entwickler zu werden. Mit
ein wenig Übung und einer guten Idee können Sie vielleicht schon bald Ihre erste
App veröffentlichen!
Aufbau des Buches
Swift ist vielen anderen Programmiersprachen sehr ähnlich, aber trotzdem werden wir uns in den ersten Kapiteln zunächst mit einfachen Dingen wie Datentypen und Kontrollstrukturen beschäftigen, denn selbst bei den Grundlagen der
Sprache gibt es Besonderheiten. Ein Schwerpunkt liegt außerdem in der Verarbeitung und Manipulation von Zeichenketten, da fast kein Programm ohne die
Ausgabe von Texten auskommt. Zusätzlich werden Sie Apples Entwicklungsumgebung Xcode kennenlernen, die in der Version 6 um einen »Spielplatz« erweitert wurde, mit dem man Swift besonders gut lernen kann. In den weiteren
Kapiteln folgen dann ein wenig anspruchsvollere Themen wie Arrays, Dictionaries, Funktionen, Klassen und Methoden. Falls Ihnen Tuples, Optionals und
Closures noch nicht vertraut sind, werden Sie diese ebenfalls kennenlernen. Nicht
fehlen dürfen selbstverständlich die Themen Vererbung und Protokolle. Was wäre
die objektorientierte Programmierung ohne sie?
Die Entwicklung von iOS-Apps füllt den zweiten Teil des Buches. Hier lernen Sie,
wie Textfelder, Schaltflächen und viele andere Steuerelemente funktionieren und
wie eine App aufgebaut ist. MVC-Architektur, Delegation und Grafik mit MultiTouch sind nur einige der behandelten Themen. Allerdings gibt es in diesem Buch
kein einzelnes Projekt, das über mehrere Kapitel hinweg erweitert wird, sondern
mehrere unabhängige Beispiele, an denen gezielt spezielle Technologien und
Anwendungsfälle erklärt werden. Zunächst sind die Projekte noch klein und überschaubar, und erst die umfangreichen Themen werden uns etwas länger beschäftigen. Obwohl die Firma Apple in ihrer Entwicklungsumgebung für viele
verschiedene Arten von Programmen Vorlagen anbietet, werden wir davon nur
wenig Gebrauch machen und die Dinge selbst programmieren. Das verlangt zwar
einen größeren Aufwand, gibt uns aber Gelegenheit, mehr über die Hintergründe
und den Aufbau einer iOS-App zu erfahren.
Teil I: Grundlagen der Sprache Swift
쐽
16
Kapitel 1: Datentypen und Optionals
Wir beginnen mit einer Einführung in die Entwicklungsumgebung Xcode und
spielen ein wenig mit Variablen und Konstanten. Dann sehen wir uns an, wie
Teil I: Grundlagen der Sprache Swift
man Zahlen rundet und aus einer Gruppe von Werten den kleinsten oder den
größten ermittelt. Optionals, eine Besonderheit von Swift, werden Sie ebenfalls
in diesem Kapitel kennenlernen.
쐽
Kapitel 2: Zeichenketten
Ohne Ausgabe von Texten sind die meisten Programme wenig nützlich, und
deshalb haben Zeichenketten ein eigenes Kapitel verdient. Swift arbeitet mit
Unicode und dort gibt es einiges zu beachten.
쐽
Kapitel 3: Arrays und Dictionaries
Eine Liste von Werten ist immer interessanter als viele einzelne Werte. Man
kann sie sortieren, filtern oder der Reihe nach ansehen. Wenn es schnell gehen
muss, helfen Wörterbücher, einen Eintrag aufzuspüren.
쐽
Kapitel 4: Fallunterscheidungen und Schleifen
Wenn Ihnen der sequenzielle Programmablauf zu langweilig ist, sollten Sie
Schleifen und Fallunterscheidungen ausprobieren. Swift bietet verschiedene
Möglichkeiten, Anweisungen zu wiederholen oder nur bedingt auszuführen.
Vorwärts oder rückwärts durch ein Array springen ist dann auch kein Problem
mehr.
쐽
Kapitel 5: Funktionen
Lassen Sie uns wiederverwendbaren Code schreiben. Den Anfang machen
Funktionen. Mit ihnen können wir Anweisungen zusammenfassen und strukturieren. Parameter und Rückgabewerte sind dann auch ganz schnell erklärt
und wir haben Zeit für Tupel und Aliasse.
쐽
Kapitel 6: Closures
Stellen Sie sich vor, Sie könnten nicht nur Werte in Variablen ablegen, sondern
auch Blöcke aus Programmcode. Mit Closures ist das möglich. Sie sind vielseitig einsetzbar und können ohne große Mühe sogar asynchron innerhalb einer
App ausgeführt werden. Genau richtig also, wenn Vorgänge, wie der Download
eines Bildes, mal wieder etwas länger dauern.
쐽
Kapitel 7: Klassen und Objekte
Die Grundlagen der objektorientierten Programmierung dürfen nicht fehlen.
Wie wird aus einer Klasse ein Objekt und was sind die Eigenschaften einer
Klasse? Dieses Kapitel verrät es!
쐽
Kapitel 8: Methoden
Methoden sind Funktionen, die zu einer Klasse gehören. Meinen Sie, damit
wäre alles gesagt? Dann lassen Sie uns über Klassenmethoden, Failable Initializers und Methoden zur Deinitialisierung reden.
쐽
Kapitel 9: Vererbung und Assoziationen
Nicht immer alles neu programmieren, sondern auf dem Bewährten aufbauen
und erweitern. Das ist ein weiterer Grundsatz der objektorientierten Program-
17
Einleitung
mierung. Wenn es dann nicht passt, lassen sich Methoden auch überschreiben.
Assoziationen können zusätzlich helfen, die einzelnen Bausteine zusammenzusetzen.
쐽
Kapitel 10: Protokolle und Extensions
Die Kommunikation zwischen verschiedenen Partnern kann kompliziert sein
und deshalb ist es wichtig, dass man sich zuvor auf ein gemeinsames Protokoll
einigt. So ist es auch in der Softwareentwicklung.
Extentions ermöglichen es, bestehende Klassen um zusätzliche Methoden zu
erweitern. Das funktioniert in Swift sogar ohne Vererbung.
쐽
Kapitel 11: Strukturen und Enumerationen
Es müssen nicht immer Klassen sein. Strukturen sind vielseitig und können in
Swift Aufgaben übernehmen, die ihnen in anderen Programmiersprachen verwehrt sind. Geschickt eingesetzt lassen sich mit ihnen einige Probleme vermeiden. Enumerationen sind auf dem Weg zu gutem Code ebenfalls eine
große Hilfe.
쐽
Kapitel 12: Sicherer Programmcode
Soll ein Programm bei fehlerhaften Daten weiterhin zuverlässig arbeiten,
muss der Code für jede Situation optimal vorbereitet werden. Kommt es trotzdem zu einem Fehler, sollte man auch damit ganz gelassen umgehen. In weiser Voraussicht haben die Entwickler von Apple einige Techniken für uns
vorbereitet.
쐽
Kapitel 13: Speicherverwaltung mit Referenzzähler
Um die Speicherverwaltung muss man sich in Swift nur selten Gedanken
machen, ganz ignorieren kann man aber das Thema nicht. Hier erfahren Sie
die Dinge, die Sie wissen sollten.
쐽
Kapitel 14: Robuste Anwendungen und automatisierte Tests
Die eigenen Projekte nach Veränderungen automatisch testen zu lassen, klingt
wie der Traum vieler Programmierer. Mit der aktuellen Version von Apples Entwicklungsumgebung ist das jetzt möglich.
Teil II: iOS-Apps
18
쐽
Kapitel 15: Lotto – 6 aus 49
In diesem Kapitel werden Sie endlich Ihre erste App entwickeln und dabei
Schaltflächen und Bezeichnungsfelder kennenlernen. Zuvor ist allerdings ein
wenig Theorie nötig und Sie erfahren, was es mit dem MVC-Entwurfsmuster
auf sich hat.
쐽
Kapitel 16: Ein Blick hinter die Kulissen
Wie startet eine App? Wie bekommt das Programm ein Icon und warum dreht
sich die Ansicht, wenn wir das Gerät drehen? Die Antworten erhalten Sie
durch einen Blick auf die internen Vorgänge.
Teil II: iOS-Apps
쐽
Kapitel 17: Eingaben mit virtuellen Tastaturen
iOS-Apps bringen ihre eigenen Bildschirmtastaturen mit und deshalb gibt es
einige Besonderheiten zu beachten. Welche Tastatur ist für welchen Anwendungsfall die richtige und wie kann eine Tastatur wieder ausgeblendet werden?
In diesem Kapitel finden Sie die Antworten.
쐽
Kapitel 18: Schieberegler, Textformatierungen und unendliche Werte
Eine App zur Berechnung des Kraftstoffverbrauchs ist optimal geeignet für den
Einsatz eines Schieberegler-Steuerelements. Ein weiterer Schwerpunkt in diesem Kapitel liegt auf der Formatierung von Zahlen in Abhängigkeit von den
aktuellen Einstellungen. Nicht überall auf der Welt wird ein Komma als Dezimaltrennzeichen verwendet.
쐽
Kapitel 19: Storyboards – Mit dem Drehbuch durch die App
Der Bildschirm eines iOS-Geräts ist klein und umfangreiche Informationen
können nur schwer angezeigt werden. Da kann ein Storyboard hilfreich sein,
um von einer Ansicht in eine andere zu wechseln. Im grafischen Editor der
Entwicklungsumgebung ergeben sich ganz neue Möglichkeiten, eine App zu
planen und zu gestalten.
쐽
Kapitel 20: Storyboards mit Protokollen
Die Kommunikation zwischen verschiedenen Klassen ist nicht immer einfach,
doch Protokolle helfen, für eine reibungslose Verständigung zu sorgen. In
einem Projekt sorgen sie zusätzlich für größere Flexibilität, mehr Sicherheit
und bessere Wiederverwendbarkeit von zuvor programmierten Komponenten.
쐽
Kapitel 21: Navigation mit einem Tableisten-Controller
Eine Tableiste ist für den Nutzer einer App eine bequeme Möglichkeit, zwischen verschiedenen Ansichten umzuschalten, und für einen erfahrenen Entwickler auch schnell umzusetzen. Das gibt mir genug Gelegenheit, das Thema
»Delegation« anzusprechen. Mit dieser Technik, die in fast allen Bereichen der
iOS-Entwicklung eingesetzt wird, erhalten wir ganz neue Möglichkeiten in
unseren Programmen.
쐽
Kapitel 22: Grafische Oberflächen ohne Interface Builder
Der grafische Editor der Entwicklungsumgebung ist ein mächtiges Werkzeug,
doch wenn es sein muss, kann die grafische Oberfläche einer App auch durch
Anweisungen im Programmcode erzeugt werden. Das schafft Flexibilität, und
Sie erfahren, wie die Kommunikation mit grafischen Elementen funktioniert.
쐽
Kapitel 23: Serialisierung – Aus dem Speicher in eine Datei
In diesem Kapitel beschäftigen wir uns wieder mit Arrays und wie man sie aus
dem Speicher des Geräts in eine Datei überträgt und wieder lädt. Außerdem
erfahren Sie, wie die Nachrichtenzentrale verschiedenen Programmteilen
dabei hilft, miteinander zu kommunizieren.
19
Einleitung
20
쐽
Kapitel 24: Der Picker – ein ganz besonderes Steuerelement
iOS verwendet viele grafische Objekte, die dem Anwender schon von DesktopAnwendungen her vertraut sind und deshalb nur wenig Umgewöhnung verlangen. Neu in der mobilen Welt ist dagegen das Picker-Steuerelement, das
auch in der Programmierung einen etwas ungewöhnlichen Weg einschlägt.
Ein weiteres Mal treffen wir auf Protokolle und Delegation.
쐽
Kapitel 25: Tabellen
Tabellen mit Master- und Detailansicht sind unter iOS ebenfalls ein spannendes Thema, das ein eigenes Kapitel mehr als verdient hat. Sehr viele Apps verwenden Tabellen, auch wenn diese manchmal gar nicht mehr als solche zu
erkennen sind.
쐽
Kapitel 26: Eye Candy – Unsere App soll schöner werden
Unsere App soll schöner werden, und Rahmen um die Bilder oder abgerundete
Ecken sind nur zwei der möglichen Verbesserungen. Gefallen dem Anwender
diese Stilmittel nicht, dann sollten wir ihm die Möglichkeit geben, sie in den
Systemeinstellungen zu deaktivieren.
쐽
Kapitel 27: Der Collection View
Das Collection-View-Steuerelement ist eine Alternative zur Tabellenansicht
und ermöglicht eine andere Darstellung von Informationen. Zusätzlich
beschäftigen wir uns in diesem Kapitel mit den Themen Drucken und wie wir
mit unseren Apps auf Twitter und Facebook Bilder und Texte veröffentlichen
können.
쐽
Kapitel 28: Zeichnen mit Core Graphics
Trotz der Vielzahl an vordefinierten Steuerelementen ist es manchmal erforderlich, den digitalen Pinsel selbst in die Hand zu nehmen und Objekte oder
Symbole, die man benötigt, selbst zu zeichnen. Das Core Graphics Framework
bietet uns nahezu unbegrenzte Möglichkeiten, kreativ zu werden und Formen
und Farbverläufe nach unseren Wünschen zu gestalten.
쐽
Kapitel 29: Multi-Touch mit Gestenerkennung
Die Möglichkeit, Berührungen auf dem Bildschirm zu erkennen und auszuwerten, ist eine der faszinierenden Eigenschaften von iPhone, iPad und iPod
touch. Mit nur wenigen Anweisungen können Sie die Objekte auf dem Bildschirm mit den Fingern verschieben, drehen oder skalieren.
쐽
Kapitel 30: Digitale und analoge Uhren mit Timern
Soll eine bestimmte Funktion einer App immer wieder ausgeführt werden,
greift der Entwickler schnell zu einem Timer. Damit ist es ein Leichtes, immer
die aktuelle Uhrzeit anzuzeigen. In diesem Kapitel bietet sich Ihnen außerdem
die Gelegenheit, zu zeigen, was Sie über Blöcke und Core Graphics inzwischen
gelernt haben. Unsere Uhr bekommt ein Zifferblatt und sogar einen Sekundenzeiger.
Swift ist nicht Objective-C Version 3.0
쐽
Kapitel 31: Lokale Benachrichtigungen
Wird Ihre App momentan nicht ausgeführt? Sie wollen den Anwender aber
trotzdem über wichtige Ereignisse informieren? Ein scheinbar unlösbares Problem – doch lokale Benachrichtigungen schaffen Abhilfe.
쐽
Kapitel 32: Karten und Koordinaten
Wo bin ich und was gibt es hier zu sehen? In diesem Kapitel beschäftigen wir
uns mit Straßenkarten und wie Sie mehr über Ihren aktuellen Standort erfahren können. In den Frameworks Core Location und Map Kit finden sich einige
sehr interessante Funktionen.
쐽
Kapitel 33: Daten suchen und finden
In einer großen Menge an Daten schnell eine gesuchte Information zu finden,
ist für jeden Programmierer eine Herausforderung. Zum Glück gibt es im iOS
bereits Funktionen, die einen Großteil der Arbeit für uns übernehmen. Eine
Tabelle für die Erweiterung einer Suchleiste ist dann auch kein großes Problem
mehr.
Swift ist nicht Objective-C Version 3.0
Bevor es im nächsten Kapitel mit der Swift-Entwicklung losgehen kann, sind
einige einführende Worte über die Programmiersprache nötig. Das gilt besonders
für alle Entwickler, die bisher mit Objective-C auf den Apple-Plattformen gearbeitet haben. Einige Dinge, die Ihnen seit Jahren vertraut sind, funktionieren jetzt
anders und müssen neu erlernt werden.
Sieht man sich als erfahrener Entwickler den Quellcode eines Swift-Programms
an, bekommt man schnell den Eindruck, es mit einer weiteren auf C basierenden
Sprache zu tun zu haben. Tatsächlich ist die Syntax von Swift anderen Sprachen
der C-Familie in manchen Bereichen ähnlich, unterscheidet sich aber in anderen
Teilen genauso oft. Swift ist zweifellos mit C verwandt, aber keineswegs mit der
Sprache kompatibel. Das war bei Objective-C, der Sprache, mit der für die ApplePlattformen bisher bevorzugt entwickelt wurde, anders. Sie können in Apples
Xcode-Entwicklungsumgebung ein Objective-C-Projekt anlegen und dort ohne
weitere Anpassungen 20 Jahre alten C-Code einfügen, ohne auf Probleme zu stoßen. Mit Swift funktioniert das nicht mehr. Die Sprache hat den Anspruch, sicher
zu sein, und muss deshalb Anforderungen erfüllen, auf die man in der Vergangenheit weniger Wert legte. So ist es beispielsweise nicht mehr möglich, bei einer
if-Struktur auf den Block aus geschweiften Klammern zu verzichten. Einige
andere Programmiersprachen erlauben das, wenn nur ein Befehl bedingt ausgeführt werden soll, aber es ist dann auch nur genau eine Anweisung. Ist der Programmcode jedoch ungünstig formatiert, kann es bei dem Entwickler leicht zu
Fehlinterpretationen kommen. Mit Swift hat Apple sich das Ziel gesetzt, solche
21
Einleitung
und ähnliche Situationen zu vermeiden. Nicht mehr schreiben muss man hingegen die runden Klammern, mit denen in vielen anderen Sprachen die Bedingung
der if-Struktur eingeklammert wird. Im Gegensatz zu dem Block aus geschweiften Klammern erhöhen sie weder die Lesbarkeit noch die Sicherheit des Codes
und auch sonst haben die Klammern keinen weiteren Nutzen.
var value = 10000
if value == 10000
{
print("Der Wert ist 10.000!")
}
else
{
print("Der Wert ist nicht 10.000.")
}
Ein Semikolon nach einer Anweisung ist in Swift ebenfalls nicht mehr erforderlich: Der Compiler kann das Ende eines Befehls ohne diese Markierung erkennen.
Sollten Sie trotzdem weiterhin Semikolons schreiben, vielleicht weil Sie das aus
jahrelanger Gewohnheit automatisch tun, wird Ihr Code trotzdem akzeptiert.
Nötig wird ein Semikolon nur, wenn Sie mehrere Anweisungen in eine Zeile
schreiben wollen. Um den Programmcode lesbar zu halten, sollte man dies aber
vermeiden.
Wie Sie in den folgenden Beispielen sehen werden, benötigt ein Swift-Programm
nicht zwingend eine main-Methode, um starten zu können. Natürlich ist es wichtig, den Startpunkt einer Anwendung genau festzulegen, allerdings ermöglicht
Swift auch Programme, die anders arbeiten. Ein »Playground« kann ein vollwertiges Programm in einer Datei abbilden, die von oben nach unten abgearbeitet wird.
Im nächsten Kapitel werden wir uns mit diesem Dokumententyp und seinen
Möglichkeiten detailliert beschäftigen.
Sind Sie bereits Entwickler für die Apple-Plattformen, werden Sie vermutlich die
eckigen Klammern vermissen, die in Objective-C immer zum Einsatz kamen,
wenn mit Klassen und Objekten programmiert wurde. Auf diese besondere Syntax
wurde in Swift ebenfalls verzichtet. Die Sprache verwendet stattdessen für Eigenschaften und Methodenaufrufe die Punktnotation, wie sie in Java und C# schon
seit vielen Jahren üblich ist. Auch das Konzept, dass sämtliche Objekte im Speicher unabhängig voneinander existieren und nur durch Nachrichten miteinander
kommunizieren, wird bei Swift nicht mehr angewendet. Dies führt zwar gegenüber Objective-C zu Einbußen in der Flexibilität, ermöglicht Swift im Gegenzug
aber schnellere Methodenaufrufe.
22
Kommentare
Kommentare
Die Syntax der Schreibweise von Kommentaren hat sich im Vergleich zu C und
Objective-C nicht verändert. Es gibt weiterhin zwei verschiedene Möglichkeiten,
Anmerkungen im Programmcode zu hinterlegen. Die erste und einfachste ist die
Kommentarzeile, eingeleitet durch zwei Schrägstriche.
// Dies ist ein Kommentar.
Kommentarzeilen eignen sich gut, um Variablen zu beschreiben. Es ist sogar
möglich, den Kommentar direkt hinter einer Anweisung einzufügen. Nach den
zwei Schrägstrichen wird der noch folgende Text zu einem Kommentar.
// Das Alter der Person
var ageOfPerson:Int = 45
var salaryOfPerson:Int = 45000 // Das Gehalt der Person
Möchte man mehr als eine Kommentarzeile in den Code einfügen, können komplette Abschnitte als Kommentarblock ausgewiesen werden. Mit der Zeichenfolge
/* beginnt ein solcher Block, der mit */ wieder beendet wird. Neben dem Einsatz
zur Dokumentation können Kommentarzeilen und Kommentarblöcke verwendet
werden, um Anweisungen vorübergehend aus einem Programm zu entfernen. So
müssen die Befehle nicht gelöscht werden, falls man sie zu einem späteren Zeitpunkt wieder benötigt.
// Eine auskommentierte Anweisung
/*
var tax:Double = 0.19
*/
Wie Sie spätestens bei unserem ersten Projekt sehen werden, sind Kommentare
im Editor der Entwicklungsumgebung immer durch eine spezielle Farbe gekennzeichnet, voreingestellt ist Grün. So lassen sich auskommentierte Anweisungen
leicht erkennen.
Nicht alle Dokumente und Lehrbücher weisen darauf hin, aber Kommentare sind
wichtig! Nicht nur für Sie, sondern auch für andere Entwickler, die vielleicht in
Zukunft mit Ihrem Programmcode in Kontakt kommen. Wenn sich die Möglichkeit bietet, sollten Sie immer versuchen, Ihre Arbeit und Erfahrungen mit anderen
Programmierern auszutauschen. Egal, wie viele Kommentare Sie schreiben, diese
haben keinerlei Einfluss auf die Dateigröße oder die Geschwindigkeit der Anwendung. Es gibt also keinen Grund, auf Kommentare im Programmcode zu verzichten! Bei den Beispielen in diesem Buch werden Sie ebenfalls viele wichtige
Anmerkungen in den Listings finden.
23
Einleitung
Stilmittel in den Listings
Das begrenzte Seitenformat dieses Buches macht es in manchen Situationen
erforderlich, den Programmcode etwas anders zu formatieren, als es in der XcodeEntwicklungsumgebung möglich wäre. Gelegentlich werden lange Befehle, die im
Texteditor auf dem Computer in eine Zeile passen, für die Codebeispiele auf mehrere Zeilen verteilt. Unabhängig von der Schreibweise ergeben sich bei den abgedruckten Listings aber keine Unterschiede in der Funktion.
An manchen Stellen im Buch werden Ihnen im Programmcode drei Punkte
begegnen, die weder eine Anweisung der Programmiersprache Swift noch ein
geheimes Zeichen der Apple-Entwickler sind:
...
Diese Markierung dient ausschließlich als Hinweis für Sie, dass es sich bei den
gezeigten Anweisungen nur um einen Ausschnitt eines schon zuvor gezeigten
Listings handelt. Die Punkte werden als Stilmittel verwendet, um im Buch nicht
wertvollen Platz mit Wiederholungen bekannten Codes zu füllen.
Wird im Laufe eines Kapitels vorhandener Programmcode geändert oder ersetzt,
sind die neuen Anweisungen innerhalb des Listings fett gedruckt. Sie müssen
dann nur diese Befehle bearbeiten. Der übrige Code bleibt unverändert.
Die Frameworks der Apple-Plattformen
Unabhängig davon, für welches System man entwickeln möchte, ist neben dem
Umgang mit der Programmiersprache oft eine umfangreiche Kenntnis der Systembibliotheken, den Frameworks, unverzichtbar.
Frameworks entbinden Entwickler von der mühevollen Aufgabe, sämtliche Komponenten für eine Anwendung eigenhändig programmieren zu müssen. Stattdessen ermöglichen sie den Zugriff auf bewährte Bausteine für nahezu sämtliche
Anwendungsfälle. Wenn man sich mit der Entwicklung für die OS-X-Plattform beschäftigt, stößt man deshalb früher oder später unvermeidlich auf den Begriff
Cocoa Framework. Der Begriff Framework ist in Verbindung mit Cocoa allerdings
nicht sehr präzise, denn hinter dieser Bezeichnung verbirgt sich kein eigenes
Framework, sondern der Zusammenschluss von drei einzelnen Bibliotheken: Application Kit, Core Data und Foundation.
Application Kit, oft abgekürzt »App Kit«, enthält die Bausteine für die Entwicklung
grafischer Benutzeroberflächen. Es enthält Klassen für die unterschiedlichsten
Steuerelemente wie beispielsweise Fenster, Schaltflächen und Schieberegler.
Durch die Verwendung eines gemeinsamen Frameworks kann sichergestellt wer-
24
Die Frameworks der Apple-Plattformen
den, dass diese Elemente in allen Programmen nicht nur gleich aussehen, sondern sich auch identisch verhalten. Eine weitere Aufgabe des Application Kits ist
die Behandlung von Ereignissen, wie das Anklicken eines Buttons, das Verschieben eines Fensters oder die Eingabe von Text in ein grafisches Textfeld.
Das Foundation Framework, gelegentlich nur als »Foundation« bezeichnet, enthält unzählige Klassen und Datenstrukturen, die es in der Sprache Swift nicht
gibt, und ist somit die wichtigste Bibliothek. Foundation kann auf eine bewegte
Geschichte zurückblicken, denn dieses Framework wurde von der Firma NeXT
entwickelt, bevor das Unternehmen von Apple übernommen wurde. Zwar wurde
Foundation seitdem mehrfach erweitert, seine Wurzeln sind aber noch immer
leicht zu erkennen. Fast alle Klassen aus dieser Bibliothek beginnen mit den Buchstaben NS, die für das Betriebssystem NeXT Step stehen, das später zu Mac OS X
wurde.
Einige Datentypen aus dem Foundation Framework braucht man in Swift nur
noch selten. So gibt es für Zeichenketten jetzt den Typ String und man muss
nicht länger die Klasse NSString verwenden, wie es bei der Objective-C-Programmierung noch der Fall ist. Nach Aussage von Apple sind die Swift-Klassen und die
bewährten Klassen aus dem Foundation Framework jedoch austauschbar. Eine
Methode, die einen NSString erwartet, würde sich problemlos mit einem String
zufriedengeben. Das ist besonders beim Einsatz von Bibliotheken von Drittanbietern wichtig. Leider fehlen den neuen Typen einige Funktionen, die besonders von
langjährigen Objective-C-Entwicklern sehr vermisst werden. Oft muss man neue
Wege gehen, um an das gleiche Ziel zu gelangen. Es spricht aber nichts dagegen,
in Swift weiterhin die aus Objective-C bekannten Klassen zu verwenden, falls das
nötig sein sollte.
Im Laufe der Jahre wurden von Apple zusätzliche Frameworks entwickelt, die
streng genommen kein Teil von Cocoa sind. Trotzdem können auch sie problemlos in Programmen eingebunden werden und funktionieren dort reibungslos mit
den anderen Komponenten. Zwei der bekanntesten Erweiterungen sind Core Animation und WebKit. Letzteres ist eine Bibliothek zur Darstellung von Internetseiten, die auch im Safari-Browser verwendet wird.
25
Einleitung
Wendet man sich der iOS-Plattform zu, bekommt man es mit dem Cocoa Touch
Framework zu tun, das ebenfalls einen Zusammenschluss einzelner Bibliotheken
darstellt. Wie man am Namen schon gut erkennen kann, findet man dort spezielle
Komponenten, um Programme durch Berührungen des Bildschirms mit den Fingern zu bedienen. Der Aufbau der grafischen Oberfläche wird deshalb nicht länger von App Kit übernommen, sondern wird zu einer Aufgabe des UIKit
Frameworks. Dieses hat seine eigenen Steuerelemente, die bei einem Einsatz
unter OS X und der Bedienung mit der Maus wenig nützlich wären.
Das Foundation Framework des Macs wurde vom iPhone übernommen, was sich
in vielen Situationen als sehr praktisch erweist. Manche Klassen, die für OS-XAnwendungen geschrieben wurden, können ohne Anpassungen in iOS-Apps
erneut verwendet werden.
Im Gegensatz zu Cocoa wurde Cocoa Touch von Anfang an großzügiger geplant
und enthält zusätzliche Frameworks. Map Kit und Core Location ermöglichen den
Zugriff auf den GPS-Empfänger und auf Straßenkarten, während Game Kit Spielen den Informationsaustausch ermöglicht. Seit einigen Jahren kann sogar der ins
Betriebssystem integrierte Twitter-Dienst von Entwicklern in eigenen Programmen genutzt werden.
Innerhalb eines Projekts ist es nicht immer einfach, zwischen Programmiersprache und Framework zu unterscheiden, denn die Bausteine sind sehr eng miteinander verzahnt. Ähnlich wie die Grammatik einer Fremdsprache ist Swift für den
Aufbau und die Syntax der Anweisungen verantwortlich, während die Klassen der
Bibliotheken das Vokabular der Sprache bilden.
Die Installation von Xcode
Das Werkzeug zur Swift-Programmierung, die Entwicklungsumgebung Xcode,
wird von der Firma Apple kostenlos zum Download angeboten und kann direkt
26
Die Installation von Xcode
aus dem Mac App Store geladen werden. Sie finden Xcode am schnellsten über die
Suchfunktion des Mac App Store. Gelegentlich steht die Entwicklungsumgebung
auch in der Liste der beliebtesten kostenlosen Anwendungen auf der Startseite.
Der Download kann ein wenig Zeit in Anspruch nehmen, denn mit einer Größe
von über 2 GB ist Xcode keine kleine Anwendung. Nachdem die Entwicklungsumgebung auf Ihren Rechner übertragen wurde, müssen Sie ein weiteres Mal Geduld
aufbringen, denn der erste Start von Xcode kann ebenfalls einige Minuten dauern.
Lassen Sie sich dabei auch nicht vom Schein trügen, es würde nichts passieren.
Ihr Computer ist fleißig mit der Installation beschäftigt, und das ist bei Xcode eine
sehr umfangreiche Aufgabe. Schon bald können Sie mit der Programmierung
beginnen.
Sämtliche Beispiele in diesem Buch benötigen Xcode, und es ist daher eine gute
Idee, die Anwendung für einen schnellen Start aus dem Ordner PROGRAMME in
das OS-X-Dock zu ziehen. Über das Kontextmenü dieser Verknüpfung können
dann auch bereits verwendete Projekte schnell neu geladen werden.
27
Einleitung
Die Entwickler-Community von Apple
Ein alternativer Weg, eine Xcode-Entwicklungsumgebung zu beziehen, führt über
die Webseite der Entwickler-Community von Apple. Dazu muss man sich allerdings als Entwickler registrieren. Diese Mitgliedschaft ist in der einfachsten Version kostenlos und bietet somit nur Vorteile. Neben den Beta-Versionen von
Xcode, mit denen Sie dann schon kommende Technologien ausprobieren können, bietet die Webseite Beispielprojekte sowie Zugriff auf die Dokumentation
und auf die Videos der vergangenen WWDC-Konferenzen. Hier kann man sehr
viel lernen.
https://developer.apple.com
Eine kostenpflichtige Mitgliedschaft wird für die Beispiele in diesem Buch nicht
benötigt. Apple möchte Geld von Ihnen, sobald Sie Ihre Programme veröffentlichen oder Technologien wie Cloud Kit nutzen wollen. iOS-Apps können Sie auch
nur als zahlendes Mitglied auf ein iOS-Gerät übertragen. Ohne diesen Mitgliedsbeitrag, der seit Anfang 2015 99 Euro pro Jahr beträgt, können Sie iOS-Projekte
nur mit dem Simulator testen, der zusammen mit Xcode installiert wird.
Webseite und Downloads zum Buch
Swift ist auf dem besten Weg, eine großartige und moderne Programmiersprache zu werden, aber trotz aller Bemühungen von Apple ist Swift in der aktuellen
Version keineswegs fertig. In den kommenden Monaten und Jahren müssen
Entwickler mit kleinen und großen Änderungen rechnen, die dann eventuell
Anpassungen an bereits bestehenden Projekten erfordern. Soweit es mir möglich ist, werde ich versuchen, diese auf meiner Webseite zu beschreiben. Sie finden die Webseite zum Buch unter der Adresse:
http://www.cocoa-coding.de/iosswift
Auf der Webseite finden Sie außerdem die einzelnen Beispielprojekte zum Download, aber auch Informationen zu anderen Themen, die es nicht in das Buch
geschafft haben. Sollten Sie Fehler im Buch finden, werde ich ebenfalls versuchen,
sie zeitnah auf der Webseite zu korrigieren.
Bei Fragen zum Buch oder wenn Sie Fehler finden, können Sie sich gerne auch
direkt an mich wenden. Meine E-Mail-Adresse finden Sie im Impressum der Webseite.
28
Teil I
Grundlagen der
Sprache Swift
In diesem Teil:
쐽
Kapitel 1
Datentypen und Optionals . . . . . . . . . . . . . . . . . . .
쐽
31
Kapitel 2
Zeichenketten. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
쐽
Kapitel 3
Arrays und Dictionaries. . . . . . . . . . . . . . . . . . . . . . 67
쐽
Kapitel 4
Fallunterscheidungen und Schleifen . . . . . . . . . . . 79
쐽
Kapitel 5
Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
쐽
Kapitel 6
Closures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
쐽
Kapitel 7
Klassen und Objekte . . . . . . . . . . . . . . . . . . . . . . . . 147
쐽
Kapitel 8
Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
쐽
Kapitel 9
Vererbung und Assoziationen. . . . . . . . . . . . . . . . . 181
29
쐽
Kapitel 10
Protokolle und Extensions . . . . . . . . . . . . . . . . . 199
쐽
Kapitel 11
Strukturen und Enumerationen . . . . . . . . . . . .
쐽
Kapitel 12
Sicherer Programmcode. . . . . . . . . . . . . . . . . . .
쐽
245
Kapitel 14
Robuste Anwendungen und automatisierte
Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
30
235
Kapitel 13
Speicherverwaltung mit Referenzzähler . . . . . .
쐽
213
251
Kapitel 1
Datentypen und Optionals
Im grundlegenden Umgang mit Variablen und Werten sind sich die meisten
modernen Programmiersprachen sehr ähnlich und unterscheiden sich oft nur in
der verwendeten Syntax. Swift ist dabei keine Ausnahme, und wenn Sie schon mit
anderen Sprachen gearbeitet haben, wird Ihnen der Inhalt der nächsten Seiten
bestimmt vertraut vorkommen. Trotzdem sollten Sie dieses Kapitel nicht überspringen, denn Swift bietet einige Besonderheiten und Anweisungen, die man in
anderen Sprachen nicht findet. Selbst bei einfachen und alltäglichen Dingen, wie
zum Beispiel der Addition von Variablen, können erfahrene Entwickler durch
Swift noch überrascht werden. Lassen auch Sie sich also überraschen!
1.1
Willkommen auf dem Spielplatz
Xcode bietet in der aktuellen Version einen besonderen Dokumententyp, der als
»Playground«, englisch für Spielplatz, bezeichnet wird. Wenn Sie in einem Playground Programmcode schreiben, wird Ihnen das Ergebnis Ihrer Arbeit oft sofort
in einer Seitenleiste neben dem Texteditor angezeigt, die von Apple als Results Sidebar bzw. als Ausgabebereich bezeichnet wird. Dort können Sie leicht überprüfen,
ob die eingegebenen Anweisungen korrekt sind und das gewünschte Ergebnis liefern. Der Spielplatz eignet sich hervorragend, um neue Dinge auszuprobieren und
zu testen, oder sich – wie in unserem Fall – mit Swift vertraut zu machen.
Einen neuen Playground können Sie direkt vom Welcome-to-Xcode-Fenster aus
erstellen, das beim Start der Entwicklungsumgebung angezeigt wird. Wählen Sie
dort GET STARTED WITH A PLAYGROUND. Möchten Sie zu einem bereits bestehenden Projekt einen Playground hinzufügen, führt der Weg über die Menüpunkte
FILE, NEW und FILE...
Ein Playground der Plattform iOS unterscheidet sich von einem OS-X-Spielplatz
nur durch die Anweisung, mit der das zugehörige Framework für die grafischen
Oberflächen importiert wird. iOS-Apps arbeiten mit UIKit, während für OS X das
Cocoa Framework importiert wird. Für unsere ersten Schritte benötigen wir
jedoch nur das Foundation Framework und somit ist es egal, für welche Plattform
Sie den Playground erzeugen. Foundation ist sowohl in UIKit als auch in Cocoa
enthalten. Nennen Sie Ihren ersten Playground Datentypen und speichern Sie die
Datei an einem Ort, an dem Sie sie später leicht wiederfinden. Sie sollten immer
31
Kapitel 1
Datentypen und Optionals
bemüht sein, Ihre Projekte gut zu organisieren, um die Übersicht nicht zu verlieren und Dinge schnell finden zu können.
Nachdem Xcode den Playground angelegt hat, öffnet die Entwicklungsumgebung
ein in zwei Bereiche geteiltes Fenster. Die linke Seite ist der Editor, in den wir
unsere Anweisungen schreiben können. Die rechte Seite wird als Ausgabebereich
bezeichnet und dient zur Ausgabe von Werten und Variablen. Neben der import-
32
1.2
Variablen und Konstanten
Anweisung und einem Kommentar gibt es im Programm sogar schon einen
Befehl. Mit
var str = "Hello, playground"
wird der Variablen str der Text Hello, playground zugewiesen, der daraufhin im
Ausgabebereich angezeigt wird. Da wir uns mit Texten erst später beschäftigen,
können Sie die Anweisung entfernen. Löschen Sie aber nicht versehentlich den
import-Befehl. Ohne ein geladenes Framework kann es in einem Swift-Programm zu verwirrenden Fehlermeldungen kommen, deren wahre Ursache nur
schwer zu erkennen ist.
1.2
Variablen und Konstanten
Lassen Sie uns bei der Reise in die Welt der Swift-Programmierung mit etwas
ganz Einfachem beginnen. Wie alle modernen Programmiersprachen bietet Swift
die Möglichkeit, im Programmcode Variablen zu deklarieren und ihnen Werte
zuzuweisen. Der von Xcode vorbereitete Playground hat das mit seiner Anweisung schon gut demonstriert. Für verschiedene Anwendungsfälle kommen dabei
dann unterschiedliche Datentypen zum Einsatz. Soll mit den Werten gerechnet
werden, fällt die Wahl in der Regel auf die Typen Int, Double oder Float, je nach
der erforderlichen Genauigkeit. Das nachfolgende kurze Listing zeigt beispielhaft
die Definition zweier Variablen mit dem Befehl var und zwei unterschiedlichen
Datentypen. Wenn Sie alle Anweisungen richtig eingegeben haben, wird Xcode im
Ausgabebereich des Playground-Fensters die Inhalte der Variablen anzeigen. An
dieser Stelle erneut der Hinweis, dass die Anweisungen auch funktionieren, wenn
Sie die Befehlszeilen aus Gewohnheit mit einem Semikolon abschließen.
33
Kapitel 1
Datentypen und Optionals
var age:Int = 43
var taxRate:Double = 9.5
Um welche Typen es sich bei den Variablen in unserem Code handelt, können Sie
vermutlich auch ohne jahrelange Erfahrung in der Softwareentwicklung und ohne
die explizite Angabe des Typs schnell selbst erkennen. Die Variable age ist eine
ganze Zahl, ein sogenannter Integer. Bei taxRate finden wir Nachkommastellen,
sodass es sich um eine Dezimalzahl handeln muss. Dort sollte dann der Typ
Double oder Float verwendet werden, denn als ganze Zahl ließe sich dieser Wert
nur unvollständig ablegen.
Wichtig
Für Variablennamen wird in Swift die Lower-Camel-Case-Schreibweise verwendet. Der erste Buchstabe im Namen ist ein kleiner Buchstabe, alle weiteren Wörter, aus denen der Name gebildet wird, beginnen mit einem Großbuchstaben.
Beispiele für aussagekräftige Namen wären arrayOfSelectedItems oder
firstDayInMonth. Unterstriche in Bezeichnern sind in Swift nicht üblich.
Wie Sie sicher bestätigen können, geben die Werte selbst schon genau vor, welcher
Datentyp verwendet werden muss, und so ist es in Swift oftmals gar nicht notwendig, den Typ einer Variablen bei der Definition explizit anzugeben. Der Compiler
kann den Typ selbst erkennen. Die Definitionen der beiden Variablen würden in
Swift daher auch so funktionieren:
var age = 43
var taxRate = 9.5
34
1.2
Variablen und Konstanten
Diese automatische Typerkennung des Compilers, die in der englischen Dokumentation als »Type Inference« bezeichnet wird, funktioniert in Swift sehr gut,
sodass bei den meisten Variablen auf eine explizite Angabe des Datentyps verzichtet wird. Als Entwickler kann man jedoch sicher sein, dass der Compiler den richtigen Typ auswählt. Außerdem wird der Programmcode so kürzer und besser
lesbar, worauf man bei Apple sehr viel Wert legt.
Für das Programm selbst ändert sich dabei jedoch nichts. Die Variable age ist weiterhin eine ganze Zahl und für Dezimalbrüche wie taxRate wählt der Compiler
immer den Typ Double, weil dieser im Vergleich zu Float über eine größere
Genauigkeit verfügt. Bei beiden Variablen wird der Typ aus den zuerst zugewiesenen Werten ermittelt. Spätere Änderungen auf einen anderen Typ sind nicht möglich. Wurde eine Variable als Int festgelegt, können Sie ihr anschließend keine
Zeichenkette zuweisen. Das folgende Beispiel wird nicht funktionieren, wie Sie
in Ihrem Playground leicht ausprobieren können. Durch Anklicken des Fehlersymbols links neben dem Programmcode können Sie die Fehlermeldung ein- oder
ausblenden.
var age = 43
var taxRate = 9.5
age = "19"
Die Deklaration und Definition einer Variablen muss in Swift keineswegs immer
in einer Programmzeile geschehen, die Anweisungen können auf mehrere Zeilen
verteilt werden. Jetzt ist der Compiler jedoch nicht mehr in der Lage, den Typ der
Variablen selbstständig zu erkennen, und benötigt unsere Hilfe. Der Typ muss bei
der Deklaration wieder explizit angegeben werden.
35
Kapitel 1
Datentypen und Optionals
var age:Int
var taxRate:Double
age = 43
taxRate = 9.5
Wie groß der Wert einer Variablen sein kann, hängt teilweise von der Systemarchitektur ab, auf der das Programm ausgeführt wird. Auf einem 32-Bit-System wird
für den Typ Int ein 32 Bit langes Datenwort verwendet, das den möglichen Wert
auf einen Bereich von -2.147.483.648 bis 2.147.483.647 eingrenzt. Auf Systemen
mit einer 64-Bit-Architektur ist Int ein 64 Bit langes Datenwort und kann Werte
zwischen -9.223.372.036.854.775.808 und 9.223.372.036.854.775.807 annehmen.
Werden explizit kleinere oder größere Datenworte benötigt, können statt Int die
Datentypen Int8, Int16, Int32 und Int64 verwendet werden. Der Typ Float ist
auf jedem System ein 32-Bit-Datenwort, Double hingegen immer 64 Bit lang. Welche Werte auf Ihrem System möglich sind, können Sie mit den folgenden vier
Aufrufen der print-Funktion herausfinden.
// Der größe Int-Wert
print(Int.max)
// Der kleinste Int-Wert
print(Int.min)
// Der größte Double-Wert
print(DBL_MAX)
// Der kleinste Double-Wert
print(DBL_MIN)
Ein Aufruf der Funktion print in einem Playground führt zu einer Ausgabe in der
Results Sidebar. Dort wird der Wert direkt neben der zugehörigen Anweisung
angezeigt. Der Ausgabebereich ist jedoch nicht der einzige Ort, an dem die Entwicklungsumgebung die Ausgaben von print anzeigt, zusätzlich werden sie in
die Konsolenansicht geschrieben. Diese ist in der Standardkonfiguration eines
Playgrounds allerdings immer unsichtbar und muss erst eingeblendet werden.
Die Schaltfläche HIDE OR SHOW THE DEBUG AREA aus der Symbolleiste erledigt
das. In der Konsole stehen die minimalen und maximalen Werte nicht neben den
36
1.2
Variablen und Konstanten
Anweisungen, sondern erscheinen in der Reihenfolge, in der sie mit print ausgegeben wurden.
In Xcode-Projekten für iOS-Apps oder OS-X-Anwendungen steht Ihnen während
der Entwicklung kein Ausgabebereich zur Verfügung, und Ihre Anweisungen werden dort auch nicht automatisch sofort nach der Eingabe ausgeführt. Das funktioniert nur im Playground. Die Konsolenansicht gibt es jedoch auch dort und
kann für Ausgaben genutzt werden. Zögern Sie nicht, print zu verwenden, um
den Programmablauf Ihrer Anwendungen nachzuvollziehen oder Werte anzuzeigen. Ein Aufruf von print verrät Ihnen nicht selten schneller etwas über Ihr Programm als die Analysewerkzeuge der Entwicklungsumgebung.
Wenn Sie den Mauspfeil auf einen Wert im Ausgabebereich bewegen, werden dort
die Schaltflächen für Inline Results und Quick Look sichtbar. Beide Funktionen bieten weitere Möglichkeiten, den Wert einer Variablen im Playground auszugeben.
Aktivieren Sie ein Inline Result, wird der Wert direkt im Codeeditor eingeblendet.
Quick Look zeigt den Wert in einem kleinen Fenster, das jedoch sofort wieder verschwindet, sobald ein beliebiger anderer Punkt auf dem Bildschirm angeklickt
wird. Die Ausgabe eines Inline Results bleibt sichtbar, bis sie wieder deaktiviert
wird.
Während Variablen zur Laufzeit eines Programms jederzeit neue Werte, allerdings
nur desselben Typs, zugewiesen werden können, ist dies bei Konstanten nicht
möglich. Konstanten werden in Softwareprojekten daher oft zur Konfiguration
eingesetzt, um Werte einer Anwendung leichter zu verwalten und »magische Zahlen« zu vermeiden. Dabei handelt es sich um Zahlenwerte, die direkt im Programmcode stehen und deren Aufgaben oft nur schwer erkennbar sind. Eine
Konstante mit einem aussagekräftigen Namen kann dann sehr zur Lesbarkeit des
Codes betragen.
In Swift werden Konstanten über den Befehl let erzeugt. Das nachfolgende Listing zeigt die Definition der Zahl Pi sowie einer Serveradresse als Zeichenkette.
37
Kapitel 1
Datentypen und Optionals
let pi = 3.14159265359
let server = "http://cocoa-coding.de"
In den ersten Versionen von Swift war es bei einer Konstanten nicht möglich,
Deklaration und Definition auf mehrere Programmzeilen zu verteilen, das funktionierte selbst dann nicht, wenn der Typ explizit angegeben wurde. Seit Swift 2.0
können Deklaration und Definition getrennt werden, in vielen anderen Programmiersprachen funktioniert das bei Konstanten nicht.
let pi:Double
pi = 3.14159265359
let server:String
server = "http://cocoa-coding.de"
Eine nachträgliche Änderung des zugewiesenen Wertes ist anschließend nicht
mehr möglich. Eine Konstante ist unveränderlich, und der Compiler wird bei dem
Versuch, Änderungen vorzunehmen, Fehlermeldungen ausgeben.
Wichtig
Swift und Xcode erlauben bei der Entwicklung die Verwendung sämtlicher Unicode-Zeichen als Variablennamen. So können Sie beispielsweise statt des Variablennamens pi auch das Zeichen U+30C0 (Greek Small Letter Pi) verwenden.
Inwieweit dies die Programmierung leichter und übersichtlicher macht, sollten
Sie für sich selbst entscheiden. Empfehlen kann man diese Vorgehensweise vermutlich nur in Ausnahmefällen.
let π = 3.14159265359
1.3
Zahlendatentypen konvertieren
Nicht selten gibt es in Programmen Situationen, bei denen die Inhalte von mehreren Variablen zu einem Wert zusammengefasst werden müssen. Ein sehr gutes
Beispiel sind mathematische Berechnungen, die aus einzelnen Werten ein Ergebnis ermitteln. Swift unterscheidet sich dabei nicht von anderen Programmiersprachen und unterstützt eine Vielzahl von Rechenoperatoren. Wie nicht anders zu
erwarten, gilt immer Punkt- vor Strichrechnung.
var a = 75
var b = 100
var c = 5
let sum1 = a + b * c
let sum2 = (a + b) * c
38
1.3
Zahlendatentypen konvertieren
Beachtenswert im gezeigten Beispiel ist der Umstand, dass auch das Ergebnis
einer Berechnung einer Konstanten zugewiesen werden kann. Im Unterschied zu
einigen anderen Programmiersprachen muss der Wert einer Konstanten in Swift
nicht zwangsläufig während der Kompilierung bekannt sein, obwohl er sich in diesem Beispiel durchaus ermitteln ließe. Sogar eine Textfeldeingabe, die erst nach
dem Start der Anwendung vorgenommen wird, kann in Swift einer Konstanten
zugewiesen werden.
Solange wir uns bei den Rechenoperationen auf nur einen Datentyp beschränken,
können wir ohne Probleme programmieren. Schwierig wird es erst, wenn unterschiedlichen Typen verwendet werden. Dann kann schon eine einfache Addition
zu Problemen führen:
var a = 75
var b = 3.8
// Die Addition unterschiedlicher Datentypen
// führt zu einer Fehlermeldung!
let sum = a + b
Auch ohne Angabe eines Typs können wir die Variable a als ganze Zahl und somit
vom Typ Int identifizieren. Bei b hingegen handelt es sich um eine Dezimalzahl,
für die der Swift-Compiler dann einen Double-Typ verwendet, sofern ihr Typ nicht
explizit als Float angegeben wird. Doch welchen Typ muss man einsetzen, wenn
die beiden Variablen addiert werden sollen? Mit einem weiteren Double wäre
sichergestellt, dass der Nachkommateil der Summe nicht verloren geht, aber in
manchen Situationen ist vielleicht genau das gewünscht und man möchte nur
ganze Zahlen. Weil der Swift-Compiler diese Entscheidung nicht eigenständig
treffen kann, führt die Addition zu einem Fehler. Schuld daran sind die unterschiedlichen Datentypen. Leider ist die Meldung der Entwicklungsumgebung
nicht besonders aussagekräftig, wenn man mit der Problematik nicht vertraut ist:
In der Softwareentwicklung unterscheidet man zwei Arten der Typkonvertierung.
Bei der impliziten Konvertierung entscheidet der Compiler selbstständig, welcher
Typ verwendet werden soll. Bei einer Berechnung, die sowohl Int als auch
Double-Typen verwendet, würde vermutlich ein Double für das Ergebnis verwendet, um eine bestmögliche Genauigkeit zu gewährleisten. Allerdings gibt es keine
Regel, dass dies so sein muss, und Programmiersprachen mit anderen Compilern
können sich anders verhalten. Damit der Entwickler sich nicht auf Vermutungen
39
Kapitel 1
Datentypen und Optionals
verlassen muss, ist in Swift eine implizite Konvertierung nicht möglich. Die
gezeigte Fehlermeldung ist die Folge.
Bei einer expliziten Konvertierung muss der gewünschte Typ im Programm genau
festgelegt werden, was somit zu einer Aufgabe für uns Programmierer wird. Soll
das Ergebnis vom Typ Double sein, müssen wir den Compiler anweisen, die Variable a vor der Addition mithilfe einer Funktion in einen Double-Typ zu konvertieren. Sind beide Summanden vom gleichen Typ, ergibt sich der Typ für die Summe.
// Die Double-Funktion:
// a wird zunächst in einen Double-Typ umgewandelt
// c wird so zu einem Double-Typ
var sumDouble = Double(a) + b
Wollen wir unser Ergebnis lieber als ganze Zahl, muss die Variable b konvertiert
werden. Doch Vorsicht, gerundet wird die Zahl von der Int-Funktion nicht! Die
Nachkommastellen werden abgeschnitten, aus 3,8 wird 3 und die Summe der
Addition somit 78! Mit einer expliziten Konvertierung erhalten wir immer den
gewünschten Typ und sind nicht von der Entscheidung eines Compilers abhängig.
// Die Int-Funktion:
// b wird zunächst in einen Int-Typ umgewandelt
// c wird so zu einem Int-Typ
var sumInt = a + Int(b)
Die gezeigten Arten der Konvertierung entsprechen einer Umwandlung, die als
»cast« oder »typecasting« bezeichnet wird, in Swift allerdings mit einer etwas
ungewöhnlichen Syntax. Viele andere Programmiersprachen verwenden eine
Schreibweise, bei der dem zu konvertierenden Wert der gewünschte Typ in runden Klammern vorangestellt wird. Dort sieht es so aus:
// Typecasting, wie es in anderen Sprachen
// angewendet wird.
// var sum = (Double)a + b
Möchte man in einem Swift-Programm zwei Int-Werte addieren, das Ergebnis
aber als Double erhalten, ist das ebenfalls nur ein kleines Problem. In den runden
Klammern der Funktionen kann die Addition programmiert werden. So ist es
nicht erforderlich, beide ganze Zahlen einzeln zu konvertieren.
var x = 100
var y = 60
// Einzelne Konvertierung, nicht erforderlich
40
1.4
Werte runden
// var sum = Double(x) + Double(y)
// Konvertierung der Summe
var sum = Double(x + y)
1.4
Werte runden
Bei einer expliziten Konvertierung von Double zu Int sämtliche Nachkommastellen abzuschneiden, kann gewünscht sein, doch nicht weniger oft möchte man den
Wert zuvor runden. Diese Aufgabe kann die Funktion round übernehmen. Wie Sie
mit den folgenden Anweisungen selbst ausprobieren können, wird ab einem
Nachkommawert von .5 aufgerundet, ansonsten wird abgerundet.
var a1 = 99.49
var r1 = round(a1)
// r1 ist jetzt 99.0
var a2 = 99.50
var r2 = round(a2)
// r2 ist jetzt 100.0
Soll der gerundete Wert dann zu einem Int-Typ werden, spricht nichts dagegen,
verschiedene Anweisungen zu verschachteln. So kann man im Code eine Zeile
einsparen, ohne dabei allzu viel Lesbarkeit einzubüßen.
var a2 = 99.50
var r2 = Int(round(a2))
// r2 ist jetzt 100 und vom Typ Int
Zwei weitere wichtige Funktionen zur Manipulation von Double-Werten sind
floor und ceil. Sie liefern den nächstniedrigeren und nächsthöheren ganzzahligen Wert, vollkommen unabhängig vom Wert hinter dem Komma. Das Ergebnis
ist weiterhin ein Double.
var aValue = 99.001
var c = ceil(aValue)
41
Kapitel 1
Datentypen und Optionals
// c ist jetzt 100.0
var f = floor(aValue)
// f ist jetzt 99.0
Einige Entwickler, die ich kennengelernt habe, hatten Schwierigkeiten, sich die
Funktionsweisen von floor und ceil zu merken und diese zu unterscheiden.
Denken Sie dabei an die englischen Begriffe. floor ist der Fußboden und somit
der niedrige, untere Wert. ceil ist eine Abkürzung für ceiling, die Zimmerdecke.
Bei dieser Funktion bekommen wir den höheren, oberen Wert. Die Zimmerdecke
ist oben und der Fußboden ist unten. Ganz einfach!
1.5
Minimum und Maximum
Wird der kleinere oder der größere Wert zweier Zahlen benötigt, kann man dies
mit einer if-Struktur sicherlich leicht programmieren. Etwas eleganter sind die in
Swift bereits vorhandenen Funktionen max und min.
var m1 = 1234
var m2 = 9876
// Den größeren und den kleineren Wert zweier
// Int-Typen ermitteln
var maximum = max(m1,m2)
var minimum = min(m1,m2)
Eine besondere Erklärung ist an dieser Stelle vermutlich nicht nötig. Erwähnenswert ist jedoch, dass die beiden Funktionen in Swift auch mehr als zwei Werte verarbeiten können. Bei den ähnlichen Funktionen anderer Programmiersprachen
ist das nicht möglich. Allerdings müssen sämtliche Werte vom gleichen Typ sein,
also ausschließlich Double, Float oder Int.
var m1 = 12.34
var m2 = 98.76
var m3 = 87.88
var m4 = 666.6
// Den größten und den kleinsten Wert aus vier
42
1.6
Der Datentyp Bool
// Double-Typen ermitteln
var maximum = max(m1,m2,m3,m4)
var minimum = min(m1,m2,m3,m4)
Eine Alternative zu min und max bieten die beiden Funktionen minElements und
maxElements, die jedoch beide eine Auflistung des Typs Array als Parameter
erwarten. Mit diesen Listen werden wir uns in Kapitel 3 noch genauer beschäftigen. Um die Funktionen auf unsere vier Variablen anzuwenden, genügt es für den
Augenblick, die Bezeichner zusätzlich in eckige Klammern einzufassen. Sämtliche Funktionen akzeptieren neben Variablen und Konstanten auch feste Werte,
die unveränderlich im Programmcode stehen.
var minValue = minElement([m1, m2, m3, m4])
var maxValue = maxElement([4.5, 4.0, 3.9, 4.4])
1.6
Der Datentyp Bool
Einen Datentyp, den man in diesem Kapitel nicht unterschlagen sollte, ist der Typ
Bool, benannt nach dem englischen Mathematiker George Boole. Eine Variable
oder Konstante des Typs Bool kann ausschließlich die Werte true oder false
annehmen und wird deshalb fast ausnahmslos dazu verwendet, um eine
bestimmte Aussage als wahr oder unwahr zu kennzeichnen. Wenn wir uns in
Kapitel 4 mit Fallunterscheidungen beschäftigen, wird der Typ Bool daher eine
große Rolle spielen.
// Zuweisungen boolescher Typen
// mit Angabe des Datentyps
var valueB1:Bool = true
// Ohne Angabe des Datentyps
var valueB2 = false
In einigen anderen Programmiersprachen kann ein Bool alternativ durch Zahlenwerte gesetzt werden, wobei 0 einem false und jeder andere Wert einem true
43
Kapitel 1
Datentypen und Optionals
entspricht. Weil so die Lesbarkeit des Codes aber sehr beeinträchtigt wird, gibt es
diese Möglichkeit in Swift 2.0 nicht mehr. Die aus Objective-C bekannten Werte
YES und NO funktionieren in Swift ebenfalls nicht.
// Alternative Zuweisung von Zahlen
// Funktioniert in Swift 2.0 nicht mehr
var value1:Bool = 1
var value2:Bool = 0
1.7
Optionals
Einer der größten Unterschiede zwischen Objective-C und Swift ist die Möglichkeit, Variablen und Konstanten im Programmcode als Optional zu deklarieren
und ihnen damit die Fähigkeit zu geben, alternativ zu einem Wert den Zustand
nil anzunehmen. Ein Optional ist nil, wenn ihm noch kein Wert zugewiesen
wurde oder sein Zustand explizit unbestimmt sein soll.
Haben Sie das alles sofort verstanden? Zugegeben, das klingt sehr technisch, aber
so ist die Softwareentwicklung gelegentlich. Möchte man Optionals an einem Beispiel aus dem Alltag erklären, muss man dafür ein wenig ausholen:
Stellen Sie sich ein digitales Thermometer vor, dessen gemessene Temperatur von
einer Software verwaltet und angezeigt werden soll. Im Sommer erreicht das Thermometer Temperaturen von über 30 Grad, im Winter hingegen Werte unter 0
Grad. So ergibt sich ein großer Bereich von möglichen Temperaturen, wobei es
sich immer um Dezimalzahlen handelt. In der Software scheint der Datentyp
Double daher bestens geeignet, die ermittelte Temperatur aufzunehmen und zur
Anzeige zu bringen. Wie Sie inzwischen wissen, müssen Variablen und Konstanten aber mit einem Wert initialisiert werden, bevor man das erste Mal lesend auf
sie zugreifen kann. Es gibt Situationen, in denen eben dies zu einem Problem
wird.
Solange das Thermometer funktioniert, hat das Programm mit der Temperatur
und dem Typ Double keine Schwierigkeiten. Problematisch wird es erst, wenn das
Thermometer ausfällt oder von der Software aus einem anderen Grund keine
Daten mehr empfangen werden können. Mit welcher Temperatur haben wir es
dann zu tun und welcher Wert soll dann angezeigt werden?
Eine Möglichkeit wäre es, die Variablen mit dem Wert 0 zu initialisieren und
somit eine Temperatur von 0 Grad anzuzeigen, wenn keine Messungen vorliegen,
aber das ist keine gute Lösung. 0 Grad ist eine der möglichen Temperaturen in
unserem Bereich, und wenn im Programm mit diesem Wert gearbeitet wird, sollte
man davon ausgehen können, dass die Temperatur so gemessen wurde. Die Software benötigt zusätzliche Informationen darüber, ob ein gemessener Wert vor-
44
1.7
Optionals
liegt, aber ein Zahlenwert des Typs Double kann darüber keine Auskunft geben.
Das Programm muss erweitert werden. Ob es sich bei dem abgelegten Wert tatsächlich um eine gemessene Temperatur handelt, ließe sich mit einer zusätzlichen booleschen Variablen abbilden. Oder Sie verwenden einen Optional!
In Swift kann jeder Typ zu einem Optional werden, allerdings ist es bei der Definition einer Variablen oder Konstanten erforderlich, diese Erweiterung explizit anzugeben, denn dass eine Variable oder Konstante ein Optional sein soll, kann der
Compiler nicht eigenständig erkennen. Er würde immer einen regulären Typ einsetzen und sich dann beschweren, wenn er für den Wert keine Zuweisung findet.
Um aus einem regulären Typ einen Optional zu machen, wird dem Datentyp ein
Fragezeichen angehängt. So erfährt der Compiler, dass dieser Wert nil sein darf.
Wenn Sie die zwei Anweisungen aus dem nächsten Listing in Ihrem Playground
eingeben, wird Ihnen Xcode für die Variable temperatur1 den Wert 32.5 im Ausgabebereich ausgeben. Für temperatur2 erhielten Sie in der Vergangenheit die
Ausgabe { Some 32.5}, wobei Some ein Hinweis auf einen Optional war. In der
momentan aktuellen Xcode-Version wird das Some leider nicht mehr angezeigt.
// Definition einer Variablen
var temperatur1:Double = 32.5
// Definition einer Variablen als Optional
var temperatur2:Double? = 32.5
Eindeutig werden die Informationen der Entwicklungsumgebung, wenn Sie die
beiden Variablen mit der print-Funktion ausgeben. Zusätzlich zum Wert für
temperatur2 wird jetzt das Wort Optional angezeigt.
...
// Ausgabe der beiden Variablen
print(temperatur1)
print(temperatur2)
45
Kapitel 1
Datentypen und Optionals
Besonders interessant verhält sich der Playground, wenn Sie für die beiden Variablen die Zuweisungen der Werte entfernen. Die Variable temperatur2 ist ein
Optional und kann legitim ohne Wert verwendet werden. Ihr Zustand ist dann
automatisch nil und genau das wird im Ausgabebereich angezeigt, sobald man
die Zuweisung entfernt.
// Definition einer Variablen
var temperatur1:Double = 32.5
// Definition einer Variablen als Optional
var temperatur2:Double?
// Ausgabe der beiden Variablen
print(temperatur1)
print(temperatur2)
Löscht man die Zuweisung für die Variable temperatur1, kommt es sofort zu
einer Fehlermeldung. Eine reguläre Variable muss vor der ersten Verwendung mit
einem Wert initialisiert werden, sonst kann sie nicht ausgegeben werden.
In Objective-C bekam man es mit nil zu tun, wenn ein Speicherzeiger auf kein
gültiges Objekt verwies, und das war nicht immer ein gewünschter Zustand. In
Swift ist nil bei einem Optional hingegen ein legitimer Wert. Er sagt aus, dass es
für die Variable keinen Wert gibt. Um dies zu ermöglichen, muss der Typ aber
explizit als Optional gekennzeichnet werden. So kann der Entwickler bestimmen,
welche Variablen und Konstanten nil sein dürfen und welche nicht.
1.8
Programmieren mit Optionals
Den Programmcode, wie er in der Software unseres digitalen Thermometers zum
Einsatz kommen könnte, zeigt das folgende Beispiel. Ist die Variable temp gleich
nil, wird der Text Keine Messung ausgegeben, gibt es hingegen einen Wert, finden wir stattdessen die Temperatur im Ausgabebereich. Probieren Sie das in Ihrer
Entwicklungsumgebung aus.
46
1.8
Programmieren mit Optionals
var temperatur:Double? = 18.2
if temperatur == nil
{
print("Keine Messung")
}
else
{
print(temperatur!)
}
Vereinfacht beschrieben, hat man es bei einem Optional immer mit zwei Werten
zu tun. Wird eine Variable oder Konstante mit ihrem Namen angesprochen, kann
man ausschließlich Informationen darüber erhalten, ob der Optional nil ist oder
nicht. Ist der Zustand nicht nil, muss zunächst ein »Auspacken« stattfinden
(Unwrapping in der englischen Dokumentation), um an den eigentlichen Wert zu
gelangen. Das geschieht, indem man dem Bezeichner ein Ausrufezeichen anhängt,
wie es im Listing mit temperatur! geschehen ist.
Jetzt wird aus einem Optional-Double ein regulärer Double-Typ und in der Entwicklungsumgebung wird der Zahlenwert ohne den Zusatz Optional angezeigt.
Auspacken sollte man einen Optional aber nur, wenn zuvor sichergestellt wurde,
dass die Variable nicht nil ist, ansonsten führt der Versuch direkt zu einem Fehler. Vergleiche mit der if-Struktur werden wir uns in den folgenden Kapiteln
genauer ansehen.
Ein anderer Weg, einen Optional auf nil zu testen und auszupacken, funktioniert
über ein Verfahren, das in Swift als Optional Binding bezeichnet wird. Dabei wird
der Optional in der if-Struktur einer neuen Konstanten oder Variablen zugewiesen. Ist die Zuweisung erfolgreich, ist der Wert also nicht nil, erhält man den
Wert automatisch in einer regulären Variablen, die aber nur innerhalb der ifStruktur verwendet werden kann.
var temperatur:Double? = 18.2
if let temp = temperatur
{
print(temp)
}
else
{
print("Keine Messung")
}
47
Kapitel 1
Datentypen und Optionals
Für Umsteiger ist das Optional Binding vielleicht etwas gewöhnungsbedürftig, es
lohnt sich aber sehr, diese Schreibweise zu verwenden, da sie zu kurzem und
übersichtlichem Code führt. Optionale Typen kommen in Swift bei vielen Klassen
und Strukturen zum Einsatz, sodass wir uns später noch mal mit diesem Thema
beschäftigen werden.
48
Kapitel 2
Zeichenketten
Neben den Typen Int, Double und Bool ist String einer der am häufigsten verwendeten Typen, denn Texte, in der Softwareentwicklung bekannt als Zeichenketten, sind für eine moderne Anwendung unverzichtbar. Zwar haben wir den Typ
String schon kurz in einigen der vorherigen Beispiele verwendet, doch das war
nur ein leichtes Kratzen an der Oberfläche. Im Gegensatz zu den Datentypen für
Zahlen lässt sich ein String auf vielfältige Weise manipulieren. Wir können
zusätzliche Zeichen anfügen oder Zeichen entfernen, Textteile tauschen oder die
Groß- und Kleinschreibung ändern. Zusätzlich gibt es in Swift Funktionen, mit
denen man prüfen kann, wie lang ein Text ist oder ob eine Zeichenkette eine
andere enthält. Es lohnt sich also, diesen Datentyp genauer zu betrachten. Um die
Beispiele auszuprobieren, legen Sie einen neuen Playground in Xcode an, den Sie
Zeichenketten nennen.
Der Datentyp String in Swift unterscheidet sich von der Klasse NSString, mit der
Entwickler auf den Apple-Plattformen bisher gearbeitet haben. Der erste Unterschied wird sichtbar, sobald man eine Zeichenkette anlegt. In Objective-C war vor
jedem Text ein @-Zeichen erforderlich, damit der Compiler Zeichenketten der
Klasse NSString von den Texten der Sprache C unterscheiden konnte. Dies war
nötig, denn Objective-C konnte mit C-Code vermischt werden. In Swift haben wir
diese Möglichkeit nicht mehr und es gibt nur einen Datentyp für Zeichenketten.
Die Definition eines Swift-Strings entspricht einer Schreibweise, wie sie in C#
oder Java verwendet wird und es muss kein * mehr angegeben werden, um eine
Variable als Speicherzeiger zu deklarieren. Die Zuweisung von einem Text zu
einer Variablen oder Konstanten funktioniert genau wie bei den Datentypen Int,
Float, Double oder dem Typ Bool.
// Definition einer Zeichenkette in Swift
// Der Datentyp müsste hier nicht angegeben werden
var text:String = "Hallo, Welt!"
// So sah die Definition einer Zeichenkette
// in Objective-C aus
// NSString *text = @"Hallo, Welt!"
Möchte man mehrere Zeichenketten zu einem Text zusammenfügen, funktioniert
das in Swift problemlos mit dem Plus-Operator (+). Obwohl man leicht den Ein-
49
Kapitel 2
Zeichenketten
druck gewinnen könnte, handelt es sich dabei nicht um eine Addition. Die einzelnen Texte werden verkettet und so wird aus 50 + 40 nicht 90, sondern 5040. Bei
Strings muss der Datentyp bei einer Variablendeklaration ebenfalls nicht mit
angegeben werden. Der Compiler kann den Typ zuverlässig erkennen.
// Strings mit dem Operator + verketten
var value = "50"
var newValue = value + "40"
// newValue ist jetzt "5040"
Der Plus-Operator ist in vielen Programmiersprachen ein gängiges Mittel, um
Texte zu verketten, und leistet auch in Swift gute Dienste. Bei umfangreichen Verkettungen kann der Programmcode aber unübersichtlich werden. Das folgende
Beispiel ist zwar noch gut zu verstehen, man muss bei der Programmierung aber
schon aufpassen, um sämtliche Teile korrekt zu verketten.
var firstName = "Georg"
var lastName = "Freitag"
// String durch Verkettung zusammengesetzt
var fullName = "Mein Name ist " + firstName + " " + lastName + "."
2.1
String Interpolation
Mehr Flexibilität und Übersicht bei der Zusammenstellung von Zeichenketten
bietet in Swift ein Verfahren, das als String Interpolation bezeichnet wird. Bei der
String Interpolation werden Variablennamen, eingebettet in \(), direkt in eine
neue Zeichenkette geschrieben. So wird der Code besser lesbar, ist leichter einzugeben und Leerzeichen werden seltener vergessen oder an den falschen Stellen
eingesetzt. Das \ ist auf deutschen Tastaturen leider nicht abgebildet. Sie finden es
auf der Taste (7), wenn Sie gleichzeitig die Tasten (ª) und (Alt) drücken.
...
// Zeichenketten werden mit der String Interpolation
// zusammengesetzt
var interpolatedFullName
= "Mein Name ist \(firstName) \(lastName)."
Nicht selten müssen in einem Projekt Zahlentypen in Zeichenketten umgewandelt werden, und das funktioniert mit der String Interpolation sehr einfach. Der
Compiler ist sogar in der Lage, Rechenoperationen innerhalb der Klammern aufzulösen. Möchten Sie das Ergebnis einer Berechnung nur anzeigen, muss es
zuvor nicht in einer eigenen Variablen oder Konstanten abgelegt werden.
50
2.1
String Interpolation
// Double-Typen mit der String Interpolation
// in einen Text umwandeln
var price = 1.339
var liter = 8.5
var total
= "\(liter) Liter zu \(price) kosten \(price * liter) €"
Preise mit drei Dezimalstellen sind nicht so ungewöhnlich, wie man vielleicht erwarten würde. Bei fast jeder Tankstelle finden Sie für den Benzinpreis an dritter Stelle
eine 9. Wollen wir in unserem Programm die Ausgabe auf zwei Dezimalstellen
beschränken, müssen wir die Umwandlung anpassen. Mit der format-Anweisung
und unter Verwendung sogenannter Format Specifier können wir dem Compiler
genau mitteilen, wie die Zahlenwerte in Texte umgewandelt werden sollen.
...
// Eine Konvertierung mithilfe von Format Specifiern
var totalFormatted
= String(format: "%.2f Liter zu %.2f kosten %.2f €",
liter, price, liter * price)
Wie das Beispiel zeigt, ist eine Konvertierung mit Format Specifiern aufwendiger als
die Umwandlung mit der String Interpolation. Zunächst werden in einen vorbereiteten Text an den Stellen Platzhalter eingefügt, wo später formatierte Variablenwerte
stehen sollen. Ein Format Specifier beginnt immer mit einem %-Zeichen und in
unserem Beispiel bestimmt %.2f, dass wir an dieser Stelle eine Dezimalzahl einsetzen wollen, die auf zwei Nachkommastellen formatiert werden soll. Sämtliche Variablen in dem Ausdruck folgen erst nach dem String. Sie werden jeweils durch ein
Komma getrennt und müssen in der gleichen Reihenfolge wie ihre zugehörigen
Platzhalter im String angegeben werden. Beachtenswert ist die Konvertierung der
Variablen liter. Sie wird auch mit %.2f formatiert und erhält somit ebenfalls zwei
Dezimalstellen. Aus dem Wert 8.5 wird die Zeichenkette 8.50. Der Preis wird zu
1.34, wobei die Ausgabe gerundet wird. Der Variablenwert von 1.339 wird nicht verändert und steht in der Variablen price weiterhin zur Verfügung.
51
Kapitel 2
Zeichenketten
Objective-C-Entwickler werden mit Format Specifiern vertraut sein, denn in dieser
Programmiersprache haben sich die Platzhalter schon über viele Jahre bewährt.
Zwei andere Format Specifier, die man kennen sollte, sind %i, als Platzhalter für
eine ganze Zahl des Typs Int, sowie %@, als Platzhalter für Objekttypen wie String.
Soll in einem formatierten String das %-Zeichen stehen, müssen Sie %% schreiben.
// Int und String konvertieren mit Format Specifiern
var firstName = "Georg"
var lastName = "Freitag"
var age = 49
var description = String(format:
"Mein Name ist %@ %@. Ich bin %i Jahre alt.",
firstName, lastName, age)
2.2
Zeichenketten vergleichen
Ob eine String-Variable Zeichen enthält, kann über die Eigenschaft isEmpty
ermittelt werden. Als Rückgabe erhalten wir einen booleschen Wert, entweder
true oder false. So lassen sich beispielsweise die Eingaben eines Benutzers
leicht überprüfen. Als alternativen Weg können wir über die Eigenschaften characters und count die Anzahl der Zeichen auswerten. Enthält ein String keine
characters, also keine Zeichen, ist die Anzahl, die vom Typ Int ist, gleich 0.
// Enthält die Zeichenkette Zeichen?
var empty:Bool = fullName.isEmpty
// Wie viele Zeichen enthält der String?
var charCount = fullName.characters.count
Sollen in Objective-C zwei Zeichenketten miteinander verglichen werden, ist eine
spezielle Methode erforderlich, denn ein == überprüft nur die Speicheradressen
zweier String-Objekte auf Gleichheit – und das ist selten die gewünschte Vorgehensweise. Wie in vielen anderen Programmiersprachen werden in Swift mit
einem == tatsächlich die Textinhalte überprüft. Mit dem folgenden Beispiel können Sie das leicht selbst überprüfen.
// Test von Zeichenketten auf Gleichheit
var aFirstName = "Petra"
var aLastName = "Brahms"
if aFirstName + " " + aLastName == "Petra Brahms"
{
52
2.2
Zeichenketten vergleichen
print("Die Zeichenketten sind gleich.")
}
else
{
print("Die Zeichenketten sind ungleich.")
}
Soll bei einer Überprüfung auf Gleichheit die Groß- und Kleinschreibung ignoriert werden, wird die Programmierung aufwendiger. Dann muss man sich der
compare-Methode von String bedienen und den Parameter NSStringCompareOptions auf CaseInsensitiveSearch setzen. Das Ergebnis dieses Vergleichs ist
dann kein boolescher Wert, sondern ein NSComparisonResult. Dieser Typ verrät
uns nicht nur, ob die Zeichenketten gleich oder ungleich sind, sondern zusätzlich,
wie sie alphabetisch sortiert sind, wenn sie sich unterscheiden. Experimentieren
Sie mit dem nächsten Beispiel, indem Sie verschiedene Wörter oder dieselben
Wörter mit unterschiedlicher Groß- und Kleinschreibung ausprobieren. Die Funktionsweise vom compare wird sich Ihnen leicht erschließen.
var city1 = "Dortmund"
var city2 = "Bochum"
// Vergleiche von city1 und city2 unter Verwendung der
// Option CaseInsensitiveSearch, um die Groß- und
// Kleinschreibung zu ignorieren.
var result:NSComparisonResult
= city1.compare(city2, options:
NSStringCompareOptions.CaseInsensitiveSearch)
if result == NSComparisonResult.OrderedSame
{
print("Die Zeichenketten sind gleich.")
}
else if result == NSComparisonResult.OrderedAscending
{
print("\(city1) kommt vor \(city2).")
}
else if result == NSComparisonResult.OrderedDescending
{
print("\(city2) kommt vor \(city1).")
}
Eine andere Möglichkeit, die Unterschiede der Groß- und Kleinschreibung bei
einem Vergleich zu ignorieren, ergibt sich, wenn beide Zeichenketten zuvor in
53
Kapitel 2
Zeichenketten
eine einheitliche Form umgewandelt werden. Über die Eigenschaft uppercaseString erhalten wir den Text eines Strings in Großbuchstaben und über lowercaseString als eine Zeichenkette ausschließlich kleiner Buchstaben.
var city1 = "Frankfurt"
var city2 = "frankFurt"
// Die Städtenamen in große Buchstaben umwandeln
var city1Upper = city1.uppercaseString
var city2Upper = city2.uppercaseString
if city1Upper == city2Upper
{
print("Die Zeichenketten sind gleich.")
}
else
{
print("Die Zeichenketten sind unterschiedlich.")
}
2.3
Textabschnitte finden und ersetzen
Gelegentlich muss in einer Software nicht genau geprüft werden, ob eine Zeichenkette einer anderen exakt entspricht, und es ist schon ausreichend, bestimmte
Buchstabenfolgen in einem Text zu entdecken. Enthält die Statusmeldung von
einem Server oder Dienst das Wort Error, ist es dort wohl zu einem Fehler gekommen, der untersucht werden muss. Fehlt dieses Wort in der Meldung, ist vermutlich alles in Ordnung. Genauso leicht könnte man differenzieren, ob eine Anrede
das Wort Herr oder das Wort Frau enthält. Bestimmt fallen Ihnen sofort andere
54
2.3
Textabschnitte finden und ersetzen
Anwendungsfälle ein. Möglich wird eine Überprüfung mit der Methode rangeOfString, wie sie das folgende Beispiel zeigt. Liefert der Aufruf ein Resultat
ungleich nil, wurde die Zeichenkette gefunden.
var city = "Hamburg"
var search = "burg"
// Prüfen, ob der Text von Variable city den Text
// der Variablen search enthält.
if city.rangeOfString(search) != nil
{
print("Die gesuchte Zeichenfolge ist enthalten.")
}
Der Rückgabewert der Methode rangeOfString ist ein Optional des Typs Range,
mit dem man viel mehr tun kann, als ihn nur auf nil zu prüfen. Wurde eine
Übereinstimmung gefunden, können wir über die Eigenschaften startIndex
und endIndex genau ermitteln, an welcher Position die gesuchte Zeichenkette mit
dem Text übereinstimmt. Durch eine zusätzliche Option kann bei rangeOfString
die Groß- und Kleinschreibung ignoriert werden. Im nächsten Listing wird ein
Optional Binding verwendet, um das Optional range in den Range-Typ validRange zu konvertieren. Das geschieht allerdings nur, wenn eine Übereinstimmung gefunden wurde, range also nicht nil ist.
...
var range
= place.rangeOfString(search, options:
NSStringCompareOptions.CaseInsensitiveSearch)
if let validRange = range
{
print("Startindex: \(validRange.startIndex)")
print("Endindex: \(validRange.endIndex)")
}
else
{
print("Die gesuchte Zeichenfolge ist nicht enthalten.")
}
Sollen Buchstaben oder Wörter in einer Zeichenkette durch andere Zeichen
ersetzt werden, kann man die Methode stringByReplacingOccurrencesOfString von String verwenden, die für genau diese Aufgabe entworfen wurde.
55
Kapitel 2
Zeichenketten
Der Austausch findet jedoch nicht »an Ort und Stelle« in der bestehenden Zeichenkette statt, sondern wir erhalten als Rückgabe des Methodenaufrufs einen
neuen Text. Diesen können wir derselben Variablen zuweisen. Im nachfolgenden
Beispiel wird bei dem Text der Variablen greetings der Begriff Objective-C
durch das Wort Swift ersetzt.
// Den Begriff Objective-C in der Zeichenkette durch
// das Wort Swift ersetzen.
var greetings
= "Hallo Objective-C-Entwickler!"
greetings
= greetings.stringByReplacingOccurrencesOfString
("Objective-C", withString: "Swift")
Das englische Wort »Occurrences« kann mit »Vorkommnisse« oder »Auftreten«
übersetzt werden und die Methode ersetzt nicht nur eines, sondern sämtliche Vorkommnisse in der Zeichenkette durch den angegebenen Parameter. Den Begriff
Objective-C finden wir nur einmal im Text, aber versuchen Sie einmal, sämtliche
e durch i zu ersetzen. Wird als Parameter ein leerer String übergeben, also "",
wird der gesuchte Text aus der ursprünglichen Zeichenkette entfernt.
Die Methode stringByReplacingOccurrencesOfString ist sehr leistungsfähig
und so ist es nicht überraschend, dass man bei ihr ebenfalls die Groß- und Kleinschreibung ignorieren kann. Der Methodenaufruf muss lediglich um einen
zusätzlichen Parameter erweitert werden.
...
// Bei der Textersetzung die Groß- und Kleinschreibung im
// Text ignorieren.
greetings
= greetings.stringByReplacingOccurrencesOfString
("hallo", withString: "Guten Tag",
options: NSStringCompareOptions.CaseInsensitiveSearch)
Handelt es sich bei Strings um Eingaben eines Anwenders, sollte man bemüht
sein, Whitespaces (Leerraum) aus den Zeichenketten zu entfernen. Bei Whitespaces handelt es sich um nicht sichtbare Zeichen wie Tabulatoren, Zeilenumbrüche oder zusätzliche Leerzeichen, die vom Nutzer versehentlich mit dem Text
eingegeben werden. Auf der grafischen Oberfläche sind diese Zeichen nicht ohne
Mühen zu erkennen, innerhalb der Programmlogik können sie aber schnell zu
Problemen führen. Ein String, der ein solches Zeichen enthält, unterscheidet sich
in der Länge und vom Inhalt her von dem gleichen Text ohne Whitespace. Schon
56
2.4
Zeichenketten in Zahlentypen konvertieren
ein einfacher Vergleich würde daher immer fehlschlagen. Glücklicherweise gibt
es in Swift eine Methode, mit der man diesem Problem entgegenwirken kann.
Der Aufruf von stringByTrimmingCharactersInSet mit dem NSCharaterSet
whitespaceCharacterSet entfernt sämtliche Whitespaces und liefert einen
bereinigten String zurück.
// Sämtliche Whitespaces aus einem String entfernen
var whitespaceString = "
Mein Name ist Andreas. "
var normalString
= whitespaceString.stringByTrimmingCharactersInSet
(NSCharacterSet.whitespaceAndNewlineCharacterSet())
Möchten Sie aus einer Zeichenkette sämtliche Zahlen entfernen, sollten Sie stringByTrimmingCharactersInSet mit dem NSCharacterSet.decimalDigitCharacter
Set ausführen. Soll die Zahl innerhalb eines Strings freigestellt werden, kann man den
gleichen Aufruf um die Eigenschaft invertedSet erweitern. Jetzt werden sämtliche
Buchstaben entfernt. Punkte und Kommata bleiben enthalten.
// Alle Buchstaben aus einem String entfernen
var whitespaceAmount = "Der Rechnungsbetrag ist: 199,44"
var normalAmount
= whitespaceAmount.stringByTrimmingCharactersInSet
(NSCharacterSet.decimalDigitCharacterSet().invertedSet)
2.4
Zeichenketten in Zahlentypen konvertieren
Mit der String Interpolation oder mit Format Specifiern ist es in Swift leicht, Zahlenwerte in Zeichenketten umzuwandeln, und mit einer gut gewählten Formatierung können die Werte sogar gerundet werden. Eine Konvertierung in die andere
Richtung, Zeichenketten zu Zahlentypen, ist hingegen schwieriger und nicht
immer erfolgreich. Einen Text in eine ganze Zahl umzuwandeln ist noch recht einfach, wie der folgende Code zeigt.
57
Kapitel 2
Zeichenketten
// Eine Zeichenkette in eine ganze Zahl umwandeln
var numericStringValue = "223"
var numericIntValue = Int(numericStringValue)
Obwohl man es auf den ersten Blick nicht erkennen kann, haben wir es hier mit
einem Optional zu tun, denn numericIntValue kann nil sein. Diesen Zustand
erhalten wir, wenn sich die Zeichenkette nicht in eine Zahl umwandeln lässt, denn
Buchstaben und andere Zeichen in numericStringValue machen die Konvertierung unmöglich. Deshalb ist es auch nicht möglich, die Variable numericIntValue als Int zu deklarieren. Wenn ein Typ angegeben werden soll, muss es ein
Int-Optional sein.
// Ungültige Zuweisung, denn die Variable muss ein
// Optional sein.
var numericIntValue:Int = Int(numericStringValue)
// Gültige Zuweisung
var numericIntValue:Int? = Int(numericStringValue)
Auf ähnlichem Weg können Zeichenketten in Double-Typen konvertiert werden,
wobei man allerdings schnell Gefahr läuft, nicht das korrekte Ergebnis zu erhalten. Der Punkt und das Koma in einer Dezimalzahl haben, je nach Region, unterschiedliche Bedeutungen. In Deutschland verwenden wir das Komma, um die
Dezimalstellen vom ganzzahligen Anteil der Zahl zu trennen, in vielen englischsprachigen Ländern wird diese Aufgabe von einem Punkt übernommen. Für eine
erfolgreiche und korrekte Umwandlung muss der Compiler wissen, welche Landeseinstellungen er verwenden soll. Die Konvertierung sollte deshalb nicht mehr
von einer einzelnen Methode übernommen werden. Man benötigt ein Objekt der
Klasse NSNumberFormatter.
Im folgenden Beispiel wird der Text numberValue zunächst in einen Zahlenwert
umgewandelt, um anschließend zurück in eine Zeichenkette konvertiert zu werden. Neben der Eigenschaft locale, mit der die Region gesetzt wird, können wir
mit minimumFractionDigits und maximumFractionDigits die minimale und
maximale Anzahl der Dezimalstellen bestimmen. Die Methode numberFromString liefert als Rückgabewert einen NSNumber-Optional, der nil ist, wenn
die Umwandlung misslingt. Bei erfolgreicher Konvertierung wird der Wert im Listing mit stringFromNumber wieder in einen String konvertiert. Das Beispiel tut
also nicht anderes, als eine Dezimalzahl, die als Zeichenkette vorliegt, auf zwei
Nachkommastellen zu begrenzen.
// Der ursprüngliche Werte als Zeichenkette
var numberValue:String = "120,3456"
58
2.4
Zeichenketten in Zahlentypen konvertieren
// Einen NSNumberFormatter erzeugen
var formatter = NSNumberFormatter()
formatter.locale = NSLocale(localeIdentifier: "de_DE")
// Minimal und maximal zwei Nachkommastellen
formatter.minimumFractionDigits = 2
formatter.maximumFractionDigits = 2
// Ein NSNumber-Typ als Optional, denn die
// Umwandlung kann fehlschlagen.
// Die explizite Angabe des Typs ist nicht zwingend, weil
// numberFromString immer einen Optional zurückgibt.
var number:NSNumber?
= formatter.numberFromString(numberValue)
if let validNumber = number
{
var newNumberValue
= formatter.stringFromNumber(validNumber)
}
Auf den ersten Blick scheint die Konvertierung aufwendig, doch es ist nicht ungewöhnlich, dass Zahlen in einem Programm zunächst als Texte vorliegen und auf
diese Art verarbeitet werden müssen. Denken Sie beispielsweise an Internetseiten,
die ausschließlich aus Texten bestehen. Außerdem sollte man nicht vergessen,
dass die Dezimalstellen der Zeichenkette nicht abgeschnitten werden, sondern die
Zahl zusätzlich gerundet wird. Wenn die Gefahr besteht, dass die Zeichenkette
zusätzlich Buchstaben enthält, sollten Sie den String zuvor mit stringByTrimmingCharactersInSet bereinigen.
Unverzichtbar wird der NSNumberFormatter, wenn die Unterschiede verschiedener Länder und deren Schreibweisen beachtet werden müssen. So erhalten wir
aus der Zeichenkette
var numberValue:String = "120.3456"
unter Verwendung der locale
formatter.locale = NSLocale(localeIdentifier: "en_US")
ebenfalls eine gerundete Zahl mit nur zwei Dezimalstellen, jetzt allerdings in der
englischen/amerikanischen Schreibweise. Die im Betriebssystem gewählte Region
59
Kapitel 2
Zeichenketten
kann in einem Projekt als currentLocale abgefragt werden. Im Zusammenspiel
mit einem NSNumberFormatter sähe das so aus:
// Die aktuellen Einstellungen für die Region
// des Betriebssystems für eine Umwandlung verwenden
formatter.locale = NSLocale.currentLocale()
2.5
Die Klasse NSNumber
Der im letzten Beispiel verwendete Typ NSNumber wird in Objective-C oft als Hilfsmittel verwendet, weil die einfachen Datentypen der Sprache C (dort int, float,
double und bool) nicht in einem Objective-C-Array verwendet werden können.
Das funktioniert ausschließlich mit Objekten, weil diese mit Speicherzeigern
arbeiten. In Swift haben wir die Einschränkung nicht, trotzdem ist NSNumber für
uns eine vielseitige Klasse. Wie Sie gesehen haben, ist sie nützlich, um eine Zeichenkette in eine Zahl zu konvertieren. Eine Umwandlung funktioniert auch mit
anderen Typen. Wird einem NSNumber-Objekt eine Dezimalzahl zugewiesen, kann
man über die Eigenschaft integerValue an den ganzzahligen Anteil des Werts
gelangen. Gerundet wird dabei nicht.
// NSNumber mit einer Dezimalzahl anlegen
var numValue:NSNumber = 4.501
// Die ganze Zahl des Wertes abrufen
var intValue:Int = numValue.integerValue
Eine Umwandlung in die andere Richtung ist ebenso leicht. Im nächsten Listing
wird aus dem Int 4 der Double 4.0. Die Angabe der Typen Int und Double dient
in beiden Beispielen der besseren Lesbarkeit. Erforderlich sind diese nicht.
// NSNumber als eine ganze Zahl anlegen
var numValue2:NSNumber = 4
// Den Wert als Dezimalzahl abrufen
var doubleValue:Double = numValue2.doubleValue
Beachtenswert ist die Konvertierung einer Zahl zu einem booleschen Wert, die mit
NSNumber ebenfalls realisiert werden kann. Der Wert 0 ergibt false, jede andere
Zahl ergibt true.
// NSNumber als eine ganze Zahl anlegen
var numValue3:NSNumber = 0
// Den Wert als booleschen Typ abrufen
var boolValue:Bool = numValue3.boolValue
60
2.6
Texte teilen
2.6
Texte teilen
Wenn es darum geht, Zeichenketten zu zerlegen oder Textabschnitte freizustellen, ist
die Programmierung mit Swift sehr leicht, denn der Typ String bringt Methoden
mit, die uns Entwicklern viel Arbeit abnehmen. Als nützlich erweisen sich substringFromIndex, mit der man eine Zeichenkette ab einer bestimmen Position ausschneiden kann, und substringToIndex, die uns einen Textabschnitt vom Anfang
bis zu einer angegebenen Position zurückgibt. Verwendet man die Methoden zusammen mit einer Range, können Textabschnitte unkompliziert erstellt werden.
Nehmen wir an, Sie möchten aus dem HTML-Quelltext einer Webseite den Titel
der Seite ermitteln. Der Titel befindet sich zwar im Kopf des Dokuments, ist dort
aber nicht zwangsläufig die erste Zeile. Erkennen kann man ihn jedoch immer an
den Tags <title> und </title>, von denen er umschlossen wird. Wie man diesen Text auslesen könnte, zeigt das folgende Listing.
Um den Programmcode flexibel zu halten, werden die zu suchenden Tags in Konstanten abgelegt. So können mit geringen Anpassungen andere Teile aus dem Text
extrahiert werden. Statt einer kompletten Webseite verwenden wir im Beispiel
einen kürzeren Text. Solange die beiden gesuchten Tags enthalten sind, haben wir
mit dem Beispiel keine Schwierigkeiten.
let startTag = "<title>"
let endTag = "</title>"
var pageTitle = ""
var htmlSource
= "Html Quelltext <title>Meine Webseite</title>
htmlSource + " Mehr Html-Quelltext"
var startRange
= htmlSource.rangeOfString(startTag, options:
NSStringCompareOptions.CaseInsensitiveSearch)
if startRange != nil
{
// Text nach dem öffnenden Tag extrahieren
pageTitle
= htmlSource.substringFromIndex(startRange!.endIndex)
var endRange
= pageTitle.rangeOfString(endTag, options:
NSStringCompareOptions.CaseInsensitiveSearch)
if endRange != nil
61
Kapitel 2
Zeichenketten
{
// Text bis zum schließenden Tag freistellen
pageTitle
= pageTitle.substringToIndex(endRange!.startIndex)
}
}
print(pageTitle)
Im ersten Schritt wird mit der Methode rangeOfString die Range für das Tag
<title> innerhalb der Zeichenkette htmlSource gesucht. Ist startRange nicht
nil, wurde das Tag im Text gefunden. Abschließend wird durch den Aufruf der
Methode substringFromIndex eine neue Zeichenkette gebildet. Sie beginnt dort,
wo in htmlSource das gesuchte <title>-Tag endet. Das wird durch die Angabe
von startRange!.endIndex realisiert. Jetzt haben wir den Anfang der Webseite
abgeschnitten.
Enden soll die Zeichenkette an der Stelle, an der das schließende Tag </title> zu
finden ist. Nun benötigen wir die Methode substringToIndex und von dem
Bereich endRange die Eigenschaft startIndex, denn das Tag selbst soll nicht Teil
des Ergebnisses sein.
Zögern Sie nicht, mit dem Beispiel zu spielen und mit den Methoden substringFromIndex und substringToIndex andere Dinge auszuprobieren. Vertauschen
Sie bei den Bereichen die Eigenschaften startIndex und endIndex. Eine andere
Methode bei der Arbeit mit Zeichenketten ist distanceTo, mit der die Länge einer
Range ermittelt werden kann. Über die Eigenschaft indices erhalten wir einen
Bereich, der die komplette Länge eines Strings umfasst.
var myProfession = "Ich bin Softwareentwickler."
// Eine Range anlegen, die den gesamten String beinhaltet
var myRange = myProfession.characters.indices
// Wie lang ist der Bereich von start bis end?
var lengthOfString =
myRange.startIndex.distanceTo(myRange.endIndex)
62
2.7
Subscripting mit Unicode
print("Die Range ist \(lengthOfString) Zeichen lang.")
// Die Zeichen zählen können wir auch mit count
var charCount = myProfession.characters.count
print("Die Range ist \(charCount) Zeichen lang.")
2.7
Subscripting mit Unicode
Benötigt man eine Variable oder Konstante, die genau ein Zeichen aufnehmen
kann, bietet sich der Typ Character an. Allerdings muss man bei der Deklaration
eines Character angeben, dass man diesen Typ verwenden möchte. Die Type
Inference des Compilers würde ansonsten, auch für Zeichenketten, die nur ein
Zeichen lang sind, den Typ String einsetzen.
// Das ist ein String
var x1 = "X"
// Das ist ein Character
var x2: Character = "X"
Swift verwendet für sämtliche Texte Unicode und so können neben dem lateinischen Alphabet zusätzlich viele andere Symbole in Zeichenketten benutzt werden.
Leider gestaltet sich die Eingabe von Unicode-Zeichen mit einer regulären Tastatur am Mac schwierig, spezielle Tastenlayouts gibt es nur für iOS-Geräte. UnicodeZeichen können alternativ über ihren Code angegeben werden.
var planet = "Earth \u{1F30D}"
Unicode-Zeichen sind nicht alle gleich lang, oder genauer ausgedrückt: Nicht alle
Zeichen benötigen gleich viel Speicherplatz. Während man bei den gebräuchlichsten Zeichen mit 16 Bit auskommt, kann ein Emoji 32 Bit belegen. Aus diesem
Grund ist es nicht möglich, einfach über die Indexposition auf ein Zeichen innerhalb der Zeichenkette zuzugreifen. Das bei vielen anderen Programmiersprachen
beliebte Subscripting, um einen Character aus einem Text auszulesen, funktioniert in Swift nicht. Zumindest nicht mit einem Integer.
var planet = "Earth \u{1F30D}"
// Subscripting funktioniert nicht mit Integern
// var symbol = planet[2]
63
Kapitel 2
Zeichenketten
Möchte man ein Zeichen an einer beliebigen Position aus einem Text auslesen,
benötigt man keinen Int-Typ, sondern einen String.Index, den man am einfachsten aus einer Range der betreffenden Zeichenkette erstellt. Die Eigenschaft
startIndex eines Bereichs verweist auf das erste Zeichen im Text, während
endIndex die Position nach dem letzten Zeichen angibt. Die erste Position auszulesen ist somit kein Problem, denn startIndex und endIndex sind vom benötigen Typ String.Index.
var planet = "Earth \u{1F30D}"
// Ein Bereich, der den gesamten String umfasst
var planetRange = planet.characters.indices
// Das erste Zeichen der Zeichenkette
var planetFirst = planet[planetRange.startIndex]
Soll das sechste Zeichen, gezählt vom Anfang der Zeichenkette, ausgelesen werden,
kommt die Methode advancedBy ins Spiel. Sie ermöglicht es, einen String.Index
zu erzeugen, der eine beliebige Anzahl von Zeichen von startIndex verschoben
ist. Dort können wir für die Zeichenanzahl mit einer ganzen Zahl arbeiten.
...
// Eine Position, sechs Zeichen entfernt vom StartIndex
var offset = 6
var stringIndex = planetRange.startIndex.advancedBy(offset)
var symbol:Character = planet[stringIndex]
Die Funktion advancedBy aus dem Listing kann man als »vorgerückt um« übersetzen. Wir erhalten eine Indexposition, die um sechs Zeichen vom Start des
String vorgerückt ist. Möchten Sie eine Position vom Ende der Zeichenkette her
zählen, können Sie advancedBy in Verbindung mit endIndex und einer negativen
ganzen Zahl verwenden.
Das Subscripting mit dem Typ String.Index funktioniert nicht nur mit einzelnen Zeichen, Abschnitte können ausgeschnitten werden, wenn man zwei Positionen angibt. Die drei Punkte im nächsten Listing kennzeichnen den Bereich als
Closed Range, einen Abschnitt, in dem die beiden angegebenen Positionen mit
enthalten sind. Es gibt auch eine Half-Open Range, doch dazu mehr in Kapitel 4.
var blindText
= "Franz jagt im komplett verwahrlosten"
blindText + " Taxi quer durch Bayern."
var blindRange = blindText.characters.indices
64
2.8
Anfang und Ende von Zeichenketten
// Der Text zwischen den Positionen 23 und 35
var substring
= blindText[blindRange.startIndex.advancedBy(23)
... blindRange.startIndex.advancedBy(35)]
2.8
Anfang und Ende von Zeichenketten
Zwei weitere String-Methoden, mit denen wir uns in diesem Kapitel beschäftigen
wollen, sind prefix und suffix. Mit ihnen können ebenfalls Abschnitte aus einer
Zeichenkette extrahiert werden. prefix liefert eine Anzahl von Zeichen vom
Anfang einer Zeichenkette und suffix Zeichen vom Ende des Textes. Obwohl sie
ähnlich arbeiten, sind sie nicht zu den Methoden substringFromIndex und substringToIndex kompatibel. prefix und suffix benötigen für die Anzahl der
Zeichen einen Int-Typ als Parameter, die zwei Methoden der Klasse String einen
String.Index-Typ, wie er bei einer Range verwendet wird. Außerdem sind prefix und suffix in der Anwendung toleranter. Wird für die Anzahl der Zeichen
ein Wert angegeben, der größer als die Länge des gesamten Strings ist, erhält man
den kompletten String. Der Versuch, eine der substring-Funktionen mit einer
Range anzuwenden, die über den String hinausgeht, führt hingegen zu einer Fehlermeldung.
var demoText
= "Falsches Üben von Xylophonmusik"
demoText + " quält jeden größeren Zwerg."
// Die ersten acht Zeichen
var pre = String(demoText.characters.prefix(8))
// Die letzten sieben Zeichen
var sub = String(demoText.characters.suffix(7))
Benötigt man von einer Zeichenkette nur das erste oder nur das letzte Zeichen,
bieten sich die Eigenschaften first und last an. Rückgabewerte beider Funktionen sind Character-Optionals, denn wenn die ursprüngliche Zeichenkette leer ist,
gibt es kein erstes und kein letztes Zeichen und der Optional ist nil.
var xylophon = "Xylophonmusik"
var firstChar:Character? = xylophon.characters.first
var lastChar:Character? = xylophon.characters.last
65
Kapitel 2
Zeichenketten
Soll von einem Text das erste oder das letzte Zeichen entfernt werden, sind dies
Aufgaben für dropFirst und dropLast.
// Das erste Zeichen entfernen
var firstDropped = String(xylophon.characters.dropFirst())
// Das letzte Zeichen entfernen
var lastDropped = String(xylophon.characters.dropLast())
Kombiniert man die Methoden, können mit geringem Aufwand alltägliche Aufgaben
erledigt werden. Im nachfolgenden Code wird die Groß- und Kleinschreibung eines
Wortes korrigiert. Der erste Buchstabe soll groß sein, alle anderen Buchstaben klein.
var reform = "reChtSchreiBrEforM"
var firstChr = reform.characters.first
reform = String(reform.characters.dropFirst())
// Zeichenkette neu zusammensetzen
reform = "\(String(firstChr!).uppercaseString)"
+ "\(reform.lowercaseString)"
Ist Ihnen aufgefallen, dass sämtliche Zuweisungen und Vergleiche ausgeführt
werden, obwohl Ihr Programm über keine main-Methode oder main-Funktion verfügt? Mit einem Programm der Sprache C wäre das nicht möglich. Bei einem Playground werden die Anweisungen ständig eingelesen, analysiert und die
Ergebnisse ausgegeben. Dieses Verfahren wird als Read-Eval-Print Loop (REPL)
bezeichnet und ist für andere Entwicklungsumgebungen schon länger gebräuchlich. Welche Informationen uns der Playground im Ausgabebereich noch anzeigen kann, werden Sie im nächsten Kapitel erfahren.
66
Kapitel 3
Arrays und Dictionaries
Mit einzelnen Variablen und Konstanten können in der Softwareentwicklung viele
Probleme gelöst werden, aber genauso oft benötigt man in einem Programm Listen, mit denen mehrere Werte gemeinsam verwaltet werden können. Swift bietet
uns für diese Aufgabe Arrays und Dictionaries, mit denen wir uns in diesem Kapitel beschäftigen wollen.
Wenn Sie die gezeigten Beispiele ausprobieren wollen, sollten Sie in Ihrer Entwicklungsumgebung einen Playground mit dem Namen Arrays anlegen. Sie finden die Beispiele auch unter dem gleichen Namen auf der Webseite zum Buch.
3.1
Arrays – Listen von Elementen
Eine Möglichkeit, eine Liste von Werten umzusetzen, führt in Swift über die Definition eines Arrays. Im einfachsten Fall handelt es sich um eine durch Kommata
getrennte Aneinanderreihung von Werten, die von eckigen Klammern eingefasst
werden. Ein Array aus Werten des Typs String mit Städtenamen würde so aussehen:
// Definition eines Arrays aus Zeichenketten
var cities
= ["Berlin", "Düsseldorf", "Frankfurt", "München", "Kiel"]
Über den Variablennamen cities können die einzelnen Zeichenketten nicht
angesprochen werden, man benötigt zusätzlich die Angabe der Position, an der
sich der gewünschte Wert in der Auflistung befindet. Die Position, oft als Index
bezeichnet, wird in eckigen Klammern hinter dem Array-Bezeichner angegeben,
sodass wir es erneut mit der Subscript-Syntax zu tun haben, die wir zuvor bei den
Zeichenketten verwendet haben. Wichtig beim Subscripting ist der Umstand, dass
sich das erste Element der Auflistung nicht an Position 1 befindet, sondern an
Position 0.
Wie das folgende Beispiel zeigt, können Variablen und Konstanten ebenfalls
einem Array hinzugefügt werden. Es muss nicht zwingend aus Werten gebildet
werden, die direkt im Programmcode stehen.
67
Kapitel 3
Arrays und Dictionaries
var city1 = "Hamburg"
let city2 = "Dortmund"
// Ein Array aus festen Werten, einer Variablen
// und einer Konstanten.
var cities
= ["Berlin", "Düsseldorf", "Frankfurt", "München", "Kiel",
city1, city2]
// Ausgabe der Stadt an der Position 5 im Array
// Zugriff auf ein Element der Liste mit Subscripting
print("Meine Stadt ist \(cities[5]).")
Wird ein Array als Variable mit var deklariert, können der Auflistung nach der ersten Initialisierung zusätzliche Werte angehängt werden. Ist das Array eine Konstante, funktioniert das nicht, dann sind die Elemente und die Anzahl der
Elemente in der Liste unveränderlich.
Wichtig
Die englische Dokumentation verwendet für Listen, die nachträglich manipuliert werden können, den Begriff »mutable« für »veränderlich«. In Swift wird ein
Array unveränderlich, sobald es als Konstante definiert wird. Objective-C verwendet stattdessen zwei verschiedene Klassen: NSArray und NSMutableArray.
Im nächsten Listing wird die Methode append und als Alternative der +=-Operator
verwendet, um das Array zu erweitern. Beide Anweisungen fügen Elemente am
Ende der Liste an. Mit dem +=-Operator ist es zusätzlich möglich, mehrere Werte
mit nur einer Anweisung anzuhängen. Faktisch wird das Array um ein weiteres
Array erweitert. Mit der append-Methode funktioniert das nicht, sie akzeptiert nur
einen einzelnen Wert.
68
3.1
Arrays – Listen von Elementen
// Weitere Städte zum Array hinzufügen
cities.append("Bonn")
cities += ["Köln"]
cities += ["Rostock", "Aachen"]
Soll einem Array ein Element nicht am Ende der Liste, sondern an einer anderen
Position hinzugefügt werden, können Sie die Methode insert verwenden. Sie
benötigt neben dem zuzufügenden Wert zusätzlich die Position, an der er eingefügt werden soll. Die nachfolgenden Elemente werden um eine Position verschoben.
// Eine weitere Stadt an Position 2 einfügen
cities.insert("Ulm", atIndex: 2)
Muss ein Element in der Auflistung ersetzt werden, ist es ausreichend, die gewünschte Position zu wählen und ihr einen anderen Wert zuzuweisen. In Swift
können auf diesem Weg sogar Abschnitte eines Arrays ersetzt werden, wobei die
Anzahl der Werte nicht identisch sein muss. Im nächsten Listing wird dem Array
an Position 1 ein Element zugewiesen und die beiden Werte an den Positionen 2
und 3 werden durch ein neues Array ersetzt, das jedoch nur ein Element enthält.
Das cities-Array wird somit kürzer. Die aktuelle Anzahl der Objekte in der Auflistung kann bei einem Array über dessen Eigenschaft count ermittelt werden.
// Ein Element im Array ersetzen
cities[1] = "Leipzig"
var count1 = cities.count
// Zwei Elemente im Array durch ein neues Element ersetzen
cities[2...3] = ["Oberhausen"]
var count2 = cities.count
69
Herunterladen