Wissen, wie’s geht.

Leseprobe

Dieses Handbuch ist der perfekte Start in die Programmiersprache Swift, mit allen Grundlagen und vielen Beispiel-Apps. In dieser Lese- probe machen Sie sich mit den Operatoren von Swift vertraut und lernen die iOS-Entwicklung anhand eines Hello-World-Programms kennen. Außerdem stellt Ihnen Michael Kofler seine Swift-Version des Spieleklassikers »Breakout« vor.

»Vorwort« »Operatoren« »Hello iOS-World!« »Breakout«

Inhaltsverzeichnis

Index

Der Autor

Leseprobe weiterempfehlen

Michael Kofler Swift 4 – Das umfassende Handbuch 1.304 Seiten, gebunden, Oktober 2017 49,90 Euro, ISBN 978-3-8362-5920-0

www.rheinwerk-verlag.de/4494

“buch” — 2017/10/6 — 8:49 — page 15 — #11

Vorwort

Apples größte Innovation des Jahres 2014 war aus meiner Sicht weder die Vorstellung der Apple Watch noch die Auslieferung des Bestsellers iPhone 6. Apple hat sich neben den Arbei- ten an diesen Produkten einer anderen Baustelle zugewandt und als Reaktion auf die vielen Mängel, die die rund 20 Jahre alte Programmiersprache Objective-C aufweist, eine vollkom- men neue Programmiersprache entwickelt: Swift! In ersten Kommentaren konnten selbst Apple-Fans ihre Skepsis nicht verbergen: Brauchen wir wirklich eine neue Programmiersprache? Doch je mehr Details Apple auf der World Wide Developers Conference (WWDC 2014) verriet, desto größer wurde die Begeisterung der teil- nehmenden Entwickler und der Fachpresse.

Warum Swift? Swift ist für Apple ein Befreiungsschlag: Objective-C dient dem Apple-Universum seit vielen Jahren als Fundament. Das ändert aber nichts daran, dass Objective-C eine Programmierspra- che aus den 1980er-Jahren ist, die in keinerlei Hinsicht mit modernen Programmiersprachen mithalten kann. Swift ist dagegen ein sauberer Neuanfang. Bei der Vorstellung wurde Swift auch Objective- CwithouttheCgenannt. Natürlich ist Swift von Objective-C beeinflusst – schließlich muss Swift kompatibel zu den unzähligen Apple-Bibliotheken sein. Swift realisiert viele neue Ideen, greift aber auch Konzepte von C#, Haskell, Java, Python und anderen Programmiersprachen auf. Daraus ergeben sich mehrere Vorteile:

Swift zählt zu den modernsten Programmiersprachen, die es momentan gibt. Code lässt sich in Swift syntaktisch eleganter formulieren als in Objective-C. Der resultierende Code ist besser lesbar und wartbar. Swift ist für Programmierer, die schon Erfahrung mit anderen modernen Sprachen gesam- melt haben, wesentlich leichter zu erlernen als Objective-C. Vorhandenes Know-how lässt sich einfacher auf Swift als auf Objective-C übertragen. Swift ist ein Open-Source-Produkt und steht auch für zur Verfügung. Der Entwick- lungsprozess erfolgt offen und transparent. Swift ist in den letzten Jahren kometenhaft in die Top-Listen der populärsten Programmier- sprachen aufgestiegen. Im TIOBE-Index war Swift zuletzt auf Platz 11 vertreten.

15

“buch”—2017/10/6—8:49—page16—#12 “buch” — 2017/10/6 — 8:49 — page 17 — #13

Vorwort Vorwort

Neu in Swift 4 fürchten: Soweit es wirklich Änderungen gibt, wird der in Xcode integrierte Code-Konverter in bewährter Manier einen Großteil der Änderungen automatisch durchführen. Langjährige Swift-Entwickler haben Swift 3 in schlechter Erinnerung: Unzählige inkompati- ble Neuerungen erforderten umfassende Änderungen an vorhandenem Code. Wesentlich Außerdem hat sich bei meiner Arbeit an den drei Auflagen dieses Buchs eines heraus- besser sieht es bei Swift 4 aus: Ein Großteil der Neuerungen sind Erweiterungen, die keine kristallisiert: Bei der App-Programmierung kostet nicht der Umgang mit Swift an sich Zeit, Inkompatibilitäten verursachen. Und da, wo doch Code-Änderungen erforderlich sind, küm- sondern die Suche nach den geeigneten Klassen, Methoden und Programmiertechniken. mert sich in der Regel der Code-Konverter von Xcode um die Anpassungen. Kurzum: Die Anpassung von Swift-3-Code an Swift 4 sollte keine großen Probleme verursachen. Ärger Was bietet dieses Buch? lauert allerdings an anderer Stelle: Veränderte Frameworks und APIs sowie Methoden und Dieses Buch vermittelt einen kompakten Einstieg in die Programmiersprache Swift in der Klassen, die plötzlich als deprecated gelten, zwingen in manchen Apps zu größeren Umbau- Version 4 (Xcode 9). Das Buch ist in vier Teile gegliedert: ten. Das wiederum ist aber nicht die Schuld von Swift. Teil I führt in die Grundlagen von Swift ein. Hier lernen Sie alle wichtigen Sprachdetails Was sind nun die wichtigsten Verbesserungen in Swift 4? kennen. Die Themenpalette reicht vom Umgang mit Variablen und elementaren Daten- Zeichenketten: Der Umgang mit Zeichenketten ist ein wenig komfortabler geworden: typen bis hin zur Syntax der objekt- und protokollorientierten Programmierung. Zum einen lassen sich jetzt sehr elegant mehrzeilige Zeichenketten formulieren, zum Teil II ist eine Einführung in die Entwicklung von Apps für iOS, macOS und tvOS. Hier anderen ist die ständige Nennung der Eigenschaft überflüssig, um auf die Sequenz der erkläre ich Ihnen beispielsweise, wie der Storyboard-Editor funktioniert, wie Sie Ihre Zeichen einer Zeichenkette zuzugreifen. Die neue Substring-Struktur macht die Verarbei- Oberfläche mit eigenem Swift-Code verbinden, eigene ViewController-Klassen entwickeln, tung von Teilzeichenketten effizienter. Weitere Optimierungen wurden im Hintergrund Apps mit mehreren Dialogen/Views organisieren etc. vorgenommen. Teil III fasst wichtige Programmiertechniken in Bausteinform zusammen. In Kurzanlei- Bereiche (Ranges): Bereiche können nun zur einen oder anderen Seite offen formuliert tungen zeige ich Ihnen unter anderem, wie Sie auf Dateien zugreifen, XML-Dokumente werden, also in der Form ar[3...] (alle Array-Elemente ab dem vierten) oder s[..

16 17

“buch” — 2017/10/6 — 8:49 — page 18 — #14

Vorwort

Leseanleitung 1300 Seiten – das kann schon abschrecken! Dazu besteht aber kein Grund. Ich habe mich beim Schreiben dieses Buchs bemüht, den Inhalt auf möglichst eigenständige Kapitel zu ver- teilen, aus denen Sie sich wie aus einem Baukasten bedienen können.

Wenn Swift für Sie vollständig neu ist, dann ist die Lektüre der ersten Kapitel aus Teil I natür- lich unumgänglich. Besonders wichtig ist, dass Sie die Swift-spezifischen Eigenheiten beim Umgang mit elementaren Datentypen und Aufzählungen (Arrays, Dictionaries etc.) kennen- lernen und das Konzept von Optionals verstehen. Interessanterweise hat sich herausgestellt, dass Sie für die Entwicklung erster Apps nicht unbedingt alle Feinheiten im Zusammenhang mit Vererbung, Protokollen etc. beherrschen müssen. Die Basics reichen zumeist. Teil II richtet sich speziell an Programmierer, die erstmalig Apps für iOS, macOS oder tvOS entwickeln. Wenn Sie bisher Objective-C zur App-Programmierung verwendet haben, werden Sie in Teil II auf viel bekanntes Wissen stoßen. Bei Teil III habe ich versucht, oft benötigte Programmiertechniken möglichst losgelöst von der Zielplattform zu beschreiben. Beispielsweise erfolgt der Umgang mit Dateien unter iOS ganz ähnlich wie unter macOS. Aus den Kapiteln in Teil III können Sie sich also bedienen, wie Sie es gerade brauchen. Viele Detailprobleme treten erst dann auf, wenn man den Schritt von kleinen Beispielen hin zu »richtigen« Apps macht. Deswegen stellt Teil IV eine Reihe vollständiger Projekte vor. Auch wenn es unwahrscheinlich ist, dass Sie genau so eine App programmieren möchten wie eines der Beispiele aus Teil IV, so werden Sie in diesen Kapiteln vermutlich doch inhaltlich ver- wandte Anleitungen und Arbeitstechniken mit einem hohen Praxisbezug finden. Probieren Sie die Apps einfach einmal aus, und blättern Sie dann durch die entsprechenden Kapitel – Sie werden sicher über Details stolpern, die sich später als hilfreich herausstellen werden.

Viel Spaß bei der App-Entwicklung! Eine neue Programmiersprache zu erlernen ist immer eine Herausforderung. Noch schwie- riger ist es, einen Überblick über die schier unüberschaubare Fülle von Bibliotheken zu gewinnen, die Sie zur App-Entwicklung brauchen. Dieses Buch soll Ihnen bei beiden Aspek- ten helfen und Ihnen ein solides Fundament vermitteln. Wenn Sie in die App-Entwicklung mit Swift einsteigen, haben Sie das Privileg, mit einer der modernsten aktuell verfügbaren Programmiersprachen zu arbeiten. Sobald Sie die ersten Schritte einmal erfolgreich absolviert haben, wird die Faszination für diese Sprache auch Sie erfassen. Bei Ihrer Reise durch die neue Welt von Swift wünsche ich Ihnen viel Spaß und Erfolg!

Michael Kofler (https://kofler.info) PS: Vielen Dank an Alfred Schilken für sein Feedback zum Manuskript!

18

“buch”—2017/10/6—8:49—page71—#67

Kapitel 3 3 Operatoren

Im Ausdruck a=b+cgelten die Zeichen = und + als Operatoren. Dieses Kapitel stellt Ihnen alle Swift-Operatoren vor – von den simplen Operatoren für die Grundrechenarten bis hin zu Swift-Spezialitäten wie dem Range-Operator n1...n2.

Leerzeichen vor oder nach Operatoren Normalerweise ist es nicht notwendig, vor oder nach einem Operator ein Leerzeichen zu schreiben. x=x+7 funktioniert genauso gut wie x=x+7. Aber wie so oft bestätigen Aus- nahmen die Regel: Swift kennt bereits standardmäßig ungewöhnlich viele Operatoren, und wenige Zeilen Code reichen aus, um weitere zu definieren. Das führt mitunter dazu, dass der Compiler nicht eindeutig erkennen kann, wo der eine Ope- rator endet und wo der nächste beginnt. Spätestens dann müssen Sie ein Leerzeichen setzen – und dann sollten Sie es vor und nach dem Operator setzen! Andernfalls glaubt der Com- piler nämlich, Sie wollten ihn explizit darauf hinweisen, dass es sich um einen Präfix- oder -Operator handelt. Im Detail sind diese Feinheiten in »The Swift Programming Lan- guage« beim Punkt »Operators« dokumentiert: https://developer.apple.com/library/content/documentation/Swift/Conceptual/ Swift_Programming_Language/LexicalStructure.html Wie rasch Probleme auftreten können, zeigt der Vergleich eines Optionals mit nil:Der Compiler betrachtet if opt!=nil als Syntaxfehler, weil er die Anweisung im Sinne von if opt! = nil interpretiert, also als Kombination zweier Operatoren. Korrekt müssen Sie den Vergleich in der Form if opt != nil formulieren.

3.1 Zuweisungs- und Rechenoperatoren

Dieser Abschnitt erläutert die zahlreichen Rechen- und Zuweisungsoperatoren. Swift kennt dabei auch Mischformen. Beispielsweise entspricht x+=3 der Anweisung x=x+3.

71

“buch” — 2017/10/6 — 8:49 — page 72 — #68 “buch” — 2017/10/6 — 8:49 — page 73 — #69

3 Operatoren 3.1 Zuweisungs- und Rechenoperatoren

Einfache Zuweisung class SimpleClass { var data=0 Der Zuweisungsoperator = speichert in einer Variablen oder Konstanten das Ergebnis des Aus- } drucks: 3 variable = ausdruck var a = SimpleClass() var b = a // a und b zeigen auf die gleichen Daten Vor der ersten Zuweisung an eine Variable bzw. Konstante muss diese mit var bzw. let als a.data = 17 solche deklariert werden: print(b.data) // deswegen ist auch b.data 17

var i = 17 i=i 2 * Arrays, Dictionaries und Zeichenketten sind Werttypen! let pi = 3.1415927 Die Unterscheidung zwischen Wert- und Referenztypen gibt es bei den meisten Program- Nicht zulässig sind Mehrfachzuweisungen in der Art a=b=3. Dafür können mehrere Variablen miersprachen. Beachten Sie aber, dass Arrays und Zeichenketten in Swift Werttypen sind und als Tupel geschrieben und gleichzeitig verändert werden: nicht, wie in vielen anderen Sprachen, Referenztypen! let (a, b, c) = (1, 7, 12)

Das funktioniert auch bei komplexeren Ausdrücken: Elementare Rechenoperatoren let (_, a, (b, c)) = (1, 2, ("x", "y")) Die meisten Rechenoperatoren sind aus dem täglichen Leben bekannt (siehe Tabelle 3.1). Der // entspricht var a=2; var b="x"; var c="y" Operator % liefert den Rest einer ganzzahligen Division: 13%5ergibt also 3,da2 * 5+3 Der Unterstrich _ ist hier ein Wildcard Pattern. Es trifft auf jeden Ausdruck zu und verhindert =13. Bei Fließkommazahlen wird der Rest zum ganzzahligen Ergebnis ermittelt. 1.0 % 0.4 im obigen Beispiel dessen weitere Verarbeitung. ergibt 0.2,da2 * 0.4 + 0.2 = 1.0 ist.

Wert- versus Referenztypen Operator Bedeutung

Swift unterscheidet bei Zuweisungen zwischen zwei grundlegenden Datentypen: + Addition

Werttypen (Value Types): Dazu zählen Zahlen, Zeichenketten, Tupel, Arrays, Dictiona- - Subtraktion ries sowie struct-undenum-Daten. Bei einer Zuweisung werden die Daten kopiert. Die Multiplikation ursprünglichen Daten und die Kopie sind vollkommen unabhängig voneinander. * Referenztypen: Objekte, also Instanzen von Klassen, sind Referenztypen. Bei einer Zuwei- / Division sung wird eine weitere Referenz auf die bereits vorhandenen Daten erstellt. Es zeigen nun % Restwert einer ganzzahligen Division zwei (oder mehr) Variablen auf dieselben Daten. &+ Integer-Addition ohne Überlaufkontrolle Die folgenden beiden Beispiele verdeutlichen den Unterschied. Im ersten Beispiel werden in x und y ganze Zahlen gespeichert, also Werttypen: &- Integer-Subtraktion ohne Überlaufkontrolle

var x = 3 &* Integer-Multiplikation ohne Überlaufkontrolle var y = x x=4 Tabelle 3.1 Rechenoperatoren print(y) // y ist unverändert 3

Für das zweite Beispiel definieren wir zuerst die Mini-Klasse SimpleClass.Ina wird eine Alle Operatoren setzen voraus, dass links und rechts von ihnen jeweils gleichartige Daten- Instanz dieser Klasse gespeichert. Bei der Zuweisung b=awird die Instanz nicht kopiert, typen verwendet werden! Im Gegensatz zu anderen Programmiersprachen erfolgen Typum- stattdessen verweist nun b auf dasselbe Objekt wie a. (In C würde man sagen, a und b sind wandlungen nicht automatisch. Zeiger.) Jede Veränderung des Objekts betrifft deswegen a gleichermaßen wie b:

72 73

“buch” — 2017/10/6 — 8:49 — page 74 — #70 “buch” — 2017/10/6 — 8:49 — page 75 — #71

3 Operatoren 3.1 Zuweisungs- und Rechenoperatoren

var a = 3 // a ist eine Integer-Variable mit der Begründung, dass die Unterscheidung zwischen der Postfix- und der Präfix-Notation, var b = 1.7 // b ist eine Fließkommavariable also zwischen i++ und ++i, zu viel Verwirrung und oft fehlerhafte Algorithmen verursacht. varc=a+b // Fehler , Int-Wert + Double -Wert nicht zulässig Wenn Sie in Swift eine Variable um eins vergrößern oder verkleinern möchten, müssen Sie 3 Wenn Sie die Summe von a plus b ausrechnen möchten, müssen Sie explizit den Datentyp dies in der Form i=i+1 oder in der Kurzschreibweise i+=1 machen. einer der beiden Operatoren anpassen. Int rundet dabei immer ab, d. h., aus 1.7 wird 1. var i=3 var c1 = a + Int(b) // c1 = 4 i++ // Fehler , steht ab Swift 3 nicht mehr zur Verfügung var c2 = Double(a) + b // c2 = 4.7 i+=1 // OK

Division durch null Inkrement- und Dekrement-Operatoren selbst gemacht Bei einer Fließkommadivision durch 0.0 lautet das Ergebnis einfach Double.infinity bzw. Wenn Sie auf die Inkrement- und Dekrement-Operatoren nicht verzichten möchten, bietet -Double.infinity. Wenn Sie hingegen mit Integerzahlen arbeiten, löst eine Division durch Swift die Möglichkeit, diese Operatoren relativ unkompliziert wieder selbst zu definieren. 0 einen Fehler aus. Fertigen Code für alle Integer-Datentypen inklusive Int8, Int16, Int32 und Int64 sowie alle UInt-Varianten finden Sie z. B. hier auf GitHub: Eine Besonderheit von Swift sind die Operatoren &+, &- und &*:SieführendieGrundrechen- https://gist.github.com/erica/6b4be87de789f32b8926388c6c6e75e9 arten für Integerzahlen ohne Überlaufkontrolle durch. Das ermöglicht die Programmierung besonders effizienter Algorithmen. Sollte allerdings doch ein Überlauf eintreten, dann ist das Ergebnis falsch! Rechnen mit Bits

var i = 10000000 // Integer Die bitweisen Operatoren &, |, ^ und ~ (AND, OR, XOR und NOT) verarbeiten ganze Zahlen var result = i &* i&* i // falsches Ergebnis bitweise. Das folgende Beispiel verwendet die Schreibweise 0b zur Kennzeichnung binärer // 3.875.820.019.684.212.736 Zahlen. String mit dem zusätzlichen Parameter radix:2 wandelt ganze Zahlen in eine Zei- Swift kennt keinen Operator zum Potenzieren. ab müssen Sie unter Zuhilfenahme der Funk- chenkette in binärer Darstellung um. tion pow berechnen. Diese Funktion ist in der Foundation-Bibliothek definiert. Sie steht nur let a = 0b11100 // Wert 28 zur Verfügung, wenn Ihr Code import Foundation enthält oder eine andere Bibliothek impor- let b = 0b01111 // Wert 15 tiert, die auf die Foundation zurückgreift. Das trifft unter anderem für Cocoa und UIKit zu. let result = a & b // Wert 12 print(String(result , radix:2)) // Ausgabe 1100 var e = 7.0 n var f = pow(e, 3.0) // 7 * 7 * 7 = 343.0 >> verschiebt die Bits einer Zahl um n Bits nach rechts (entspricht einer Division durch 2 ), << verschiebt entsprechend nach links (entspricht einer Multiplikation mit 2n). >>> funktioniert Zeichenketten aneinanderfügen wie >>, betrachtet die Zahl aber so, als wäre sie vorzeichenlos.

Der Operator + addiert nicht nur zwei Zahlen, sondern fügt auch Zeichenketten aneinander: let e = 16 let f = e << 2 // entspricht f=e*4, Ergebnis 64 var s1 = "Hello" let g = e >> 1 // entspricht g=e/2, Ergebnis 8 var s2 = "World!" var hw = s1 + ""+s2 // "Hello World!" Wenn Sie Daten bitweise verarbeiten, ist es oft zweckmäßig, anstelle gewöhnlicher Integer- Zahlen explizit Datentypen ohne Vorzeichen zu verwenden, z. B. UInt32 oder UInt16.Das Inkrement und Dekrement folgende Beispiel verwendet 0x zur Kennzeichnung hexadezimaler Zahlen: Wie viele andere Programmiersprachen kannte Swift bis zur Version 2 die Inkrement- und let rgb: UInt32 = 0x336688 let red: UInt8 = UInt8( (rgb & 0xff0000) >> 16 ) Dekrement-Operatoren ++ und --. In Swift 3 wurden diese Operatoren allerdings eliminiert,

74 75

“buch”—2017/10/6—8:49—page76—#72 “buch” — 2017/10/6 — 8:49 — page 77 — #73

3 Operatoren 3.2 Vergleichsoperatoren und logische Operatoren

Kombinierte Rechen- und Zuweisungsoperationen "A" < "a" // true "a" < "ä" // true Alle bereits erwähnten Rechenoperatoren sowie die logischen Operatoren && und || können "ä" < "b" // true mit einer Zuweisung kombiniert werden. Dazu muss dem Operator das Zeichen = folgen. 3 Details zu den logischen Operatoren folgen im nächsten Abschnitt. Mehr Details zur Sortierordnung von Zeichenketten und zu Ihren Möglichkeiten, diese zu beeinflussen, folgen in Kapitel 8, »Zeichenketten«. x+=y // entspricht x = x + y x-=y // entspricht x = x - y x *=y // entspricht x = x * y == versus === x/=y // entspricht x = x / y Zum Vergleich von Objekten kennt Swift neben == und != auch die Varianten === und !==. x%=y // entspricht x = x % y Dabei testet a===b, ob die beiden Variablen a und b auf dieselbe Instanz einer Klasse zeigen. x<<=y // entspricht x = x << y Hingegen überprüft a==b,oba und b zwei Objekte mit übereinstimmenden Daten sind. Das x>>=y // entspricht x = x >> y x&=y // entspricht x = x & y ist nicht das Gleiche! Es ist ja durchaus möglich, dass zwei unterschiedliche Objekte dieselben x &&= y // entspricht x = x && y Daten enthalten. x|=y // entspricht x = x | y x ||= y // entspricht x = x || y Einschränkungen x^=y // entspricht x = x ^ y Die Operatoren === und !== können nur auf Referenztypen angewendet werden, nicht auf Werttypen (wie Zahlen, Zeichenketten, Arrays, Dictionaries sowie sonstige Strukturen). 3.2 Vergleichsoperatorenund logischeOperatoren Umgekehrt können die Operatoren == und != bei selbst definierten Klassen nur verwen- det werden, wenn Sie für diese Klassen den Operator == selbst implementieren (Protokoll Um Bedingungen für Schleifen oder Verzweigungen zu formulieren, müssen Sie Variablen Equatable, siehe Abschnitt 12.4, »Standardprotokolle«). vergleichen und oft mehrere Vergleiche miteinander kombinieren. Dieser Abschnitt stellt Ihnen die dazu erforderlichen Operatoren vor. Die folgenden Zeilen definieren zuerst die Klasse Pt zur Speicherung eines Koordinaten- punkts und dann den Operator == zum Vergleich zweier Pt-Objekte. Damit ist das Beispiel Vergleichsoperatoren gleich auch ein Vorgriff auf die Definition eigener Operatoren.

Die Vergleichsoperatoren ==, != (ungleich), <, <= sowie > und >= können gleichermaßen für class Pt { Zahlen und für Zeichenketten eingesetzt werden. Wie bei anderen Operatoren ist es wichtig, var x: Double , y: Double // Init-Funktion dass auf beiden Seiten des Operators der gleiche Datentyp verwendet wird; Sie können also init(x: Double , y: Double){ nicht eine ganze Zahl mit einer Fließkommazahl vergleichen! self.x=x 1==2 // false self.y=y 1<2 // true } } "abc" == "abc" // true // Operator zum Vergleich von zwei Pt-Objekten "abc" == "Abc" // false func ==(left: Pt, right: Pt) -> Bool { return left.x == right.x && left.y == right.y Zeichenketten gelten dann als gleich, wenn auch die Groß- und Kleinschreibung überein- } stimmt. Etwas schwieriger ist die Interpretation von größer und kleiner. Grundsätzlich gelten Großbuchstaben als kleiner als Kleinbuchstaben, d. h., sie werden beim Sortieren vorne ein- // == versus === gereiht. Internationale Zeichen werden auf der Basis der Unicode-Normalform D verglichen. var p1 = Pt(x: 1.0, y: 2.0) Die deutschen Buchstaben ä, ö oder ü werden dabei wie eine Kombination aus zwei Zeichen var p2 = Pt(x: 1.0, y: 2.0) betrachtet, beispielsweise ä = a".Somitgilt: p1 == p2 // true, weil die Objekte dieselben Daten enthalten p1 === p2 // false, weil es unterschiedliche Objekte sind

76 77

“buch”—2017/10/6—8:49—page78—#74 “buch” — 2017/10/6 — 8:49 — page 79 — #75

3 Operatoren 3.2 Vergleichsoperatoren und logische Operatoren

Vergleiche mit ~= as: In dieser Form eignet sich as nur, wenn der Compiler erkennen kann, dass die Umwand- lung gefahrlos möglich ist. Das trifft auf alle Upcasts zu, also auf Umwandlungen in Swift kennt mit ~= einen weiteren Vergleichsoperator mit recht wenigen Funktionen: Instanzen einer übergeordneten Klasse (siehe Abschnitt 12.1, »Vererbung«), außerdem bei Zwei Ausdrücke des gleichen Typs werden wie mit == verglichen. manchen Literalen (z. B. 12 as Float). 3 Außerdem kann getestet werden, ob eine ganze Zahl in einem durch den Range-Operator as?: Der Downcast-Operator as? typ stellt vor der Typkonvertierung sicher, dass diese formulierten Zahlenbereich enthalten ist. überhaupt möglich ist. Wenn das nicht der Fall ist, lautet das Ergebnis nil.Estrittkein -2...2 ~= 1 // true Fehler auf. -2...2 ~= -2 // true Mit if let varname = ausdruck as? typ können Sie den Typtest mit einer Zuweisung kom- -2...2 ~= 2 // true binieren. Das funktioniert gleichermaßen für Konstanten (let wie im folgenden Beispiel) -2...2 ~= 4 // false wie auch für Variablen (var): Achten Sie darauf, dass Sie zuerst den Bereich und dann den Vergleichswert angeben müs- func f(obj: Any) { sen. Wenn Sie die Reihenfolge vertauschen, funktioniert der Operator nicht. Details zu if let myint = obj as? UInt32 { Range-Operatoren folgen gleich in Abschnitt 3.3. // myint hat den Datentyp UInt32 Analog kann auch in switch-Ausdrücken mit case überprüft werden, ob sich ein ganzzahliger ... Ausdruck in einem vorgegebenen Bereich befindet: } else { print("falscher Datentyp") let n = 12 } switch n{ } case (1...10): as!: Mit einem nachgestellten Ausrufezeichen wird die Konvertierung auf jeden Fall ver- print("Zahl zwischen 1 und 10") sucht. Dabei kann es zu einem Fehler kommen, wenn der Datentyp nicht passt. Insofern case(11...20): ist diese Variante zumeist nur zweckmäßig, wenn die Typüberprüfung im Voraus erfolgt. print("Zahl zwischen 11 und 20") let obj: Any = 123 default: if obj is UInt32 { print("Andere Zahl") // wird nicht ausgeführt, weil obj eine Int-Instanz enthält } var myint = obj as! UInt32 }

Datentyp-Vergleich (»is«)

Mit dem Operator is testen Sie, ob eine Variable einem bestimmten Typ entspricht: Upcasts und Downcasts Ein Grundprinzip der objektorientierten Programmierung ist die Vererbung. Damit können func f(obj: Any) { Klassen die Merkmale einer Basisklasse übernehmen und diese erweitern oder verändern. Ein if obj is UInt32 { print("Datentyp UInt32") Objekt einer abgeleiteten Klasse (im Klassendiagramm unten dargestellt) kann immer wie ein ... Objekt der Basisklasse verwendet werden (im Klassendiagramm oben). Das nennt man einen } (impliziten) Upcast, also eine Umwandlung in der Klassenhierarchie nach oben. } Eine Konvertierung in die umgekehrte Richtung ist ein Downcast. Dieser funktioniert nur, wenn eine Variable vom Typ der Basisklasse tatsächlich ein Objekt der erforderlichen ab- Casting-Operator (»as«) geleiteten Klasse enthält. Mehr Details zu diesem Thema finden Sie in Abschnitt 12.1, »Ver- erbung«. Mit dem Operator as wandeln Sie, sofern möglich, einen Datentyp in einen anderen um. Der Operator hat in Swift drei Erscheinungsformen:

78 79

“buch”—2017/10/6—8:49—page80—#76 “buch”—2017/10/6—8:49—page81—#77

3 Operatoren 3.3 Range-Operatoren

Logische Operatoren wobei hier anstelle der Zahlen n1 bzw. n2 Elemente der Struktur String.Index verwendet wer- den müssen. Logische Operatoren kombinieren Wahrheitswerte. Wahr UND Wahr liefert wieder Wahr; Wahr UND Falsch ergibt hingegen Falsch. In Swift gibt es wie in den meisten anderen Pro- Normalerweise werden diese Range-Operatoren für ganze Zahlen bzw. String-Positionen ver- 3 grammiersprachen die drei logischen Operatoren ! (Nicht), && (Und) sowie || (Oder): wendet. Es gibt aber auch Anwendungsfälle für Fließkommazahlen und Zeichenketten.

let a=3, b=5 Intern sind die Range-Operatoren Kurzschreibweisen zur Erzeugung diverser XxxxRange- a>0 && b<=10 // true Strukturen: a>b || b>a // true 1..<10 // entspricht CountableRange (1..<10) let ok = (a>b) // false 1...10 // entspricht CountableClosedRange (1...10) if !ok { // wenn ok nicht true ist, dann ... print("Fehler") // ... eine Fehlermeldung ausgeben Bei beidseitig geschlossen Bereichen lauten die wichtigsten Eigenschaften startIndex und } endIndex. Sie geben den Start- bzw. Endwert des Bereichs an. contains überprüft, ob eine && und || führen eine sogenannte Short-Circuit Evaluation aus: Steht nach der Auswertung bestimmte Zahl im Zahlenbereich enthalten ist: des ersten Operanden das Endergebnis bereits fest, wird auf die Auswertung des zweiten Aus- var r1 = 1..<10 // entspricht r = CountableRange (1..<10) drucks verzichtet. Wenn im folgenden Beispiel a>b das Ergebnis false liefert, dann ruft Swift r1.startIndex // 1 die Funktion calculate gar nicht auf; der logische Ausdruck ist in jedem Fall false,ganzegal, r1.endIndex // 10 welches Ergebnis calculate liefern würde. r1.contains(7) // true r1.contains(11) // false if a>b && calculate(a, b)==14 { ... } Bei einseitigen Bereichen geben lowerBound bzw. upperBound die obere bzw. untere Grenze an:

let r2 = 17... // entspricht CountablePartialRangeFrom (17) 3.3 Range-Operatoren r2.lowerBound // 17 r2.contains(23) // true In Swift gibt es fünf Operatoren, um Zahlenbereiche auszudrücken (siehe Tabelle 3.2). Bei den ersten beiden Varianten muss n1 kleiner als n2 sein, sonst ist der Ausdruck ungültig. Darüber hinaus gibt es unzählige Methoden, um den Zahlenbereich zu verändern (dropFirst, dropLast, reversed) bzw. um seine Elemente zu verarbeiten (filter, forEach, map):

Operator Interne Darstellung Bedeutung (1...5).map { print($0 * 2) } // Ausgabe 2, 4, 6, 8, 10

n1...n2 CountableRange n1 bis inklusive n2 (1...3 entspricht 1, 2, 3) Range-Operatoren in Schleifen n1..20 {break} ab, worauf die Operatoren angewendet werden. Wenn der Bereich auf die Elemente eines print(i) // Ausgabe 10, 11, ..., 20 Arrays angewendet wird, dann beginnt ...n2 bzw. ..

80 81

“buch” — 2017/10/6 — 8:49 — page 82 — #78 “buch” — 2017/10/6 — 8:49 — page 83 — #79

3 Operatoren 3.3 Range-Operatoren

Range-Operatoren und Arrays Range-Operatoren für Fließkommazahlen

In der folgenden Schreibweise können Sie Zahlenbereiche zur Initialisierung eines Integer- Als Vergleichsbasis für switch bzw. für den Operator ~= dürfen auch Fließkommabereiche Arrays verwenden: gebildet werden: 3 var ar = [Int](1...10) // entspricht var ar = [1, 2, ..., 10] 1.7..<2.9 ~= 2.3 // true

Anstelle des üblichen Zugriffs auf ein Array-Element mit array[n] können Sie auch einen Allerdings gelten für Bereiche, deren Grunddatentyp nicht aufzählbar ist, viele Einschränkun- Bereich für den Zugriff auf mehrere Elemente angeben. Die folgenden Beispiele zeigen die gen. Beispielsweise ist es unmöglich, Schleifen über sie zu bilden: Anwendung aller fünf Range-Operatoren. Beachten Sie, dass das Ergebnis kein neues Array ist, sondern eine ArraySlice-Struktur. Beachten Sie auch, dass Array-Indizes immer mit 0 Schleifen über einen Fließkommazahlenbereich beginnen. array[0] ist also das erste Element, array[...2] meint daher alle Elemente bis zum dritten. Mehr Informationen zum Umgang mit Arrays folgen in Kapitel 10, »Arrays, Dictiona- Um analog zu for i in 1...3 eine Schleife für eine double-Variable zu formulieren, können ries, Sets und Tupel«. Sie auf stride zurückgreifen. Diese Funktion stelle ich Ihnen in Kapitel 5, »Verzweigungen und Schleifen«, vor. let data = ["a", "b", "c", "d", "e"] // Datentyp Array data[2...4] // ["c", "d", "e"], Datentyp ArraySlice data[2..<4] // ["c", "d"] Range-Operatoren für Zeichenketten data[3...] // ["d", "e"] data[...2] // ["a", "b", "c"] Für Vergleiche mit einzelnen Zeichen bzw. in switch-Konstruktionen können Sie auch Zei- data[..<2] // ["a", "b"] chenbereiche verwenden. Wie bei Fließkommazahlen ist aber eine Anwendung in Schleifen nicht zulässig.

Range-Operatoren in switch-Konstrukten "a"..."z" ~= "f" // true "0"..."9" ~= "x" // false Mit dem vorhin schon vorgestellten Operator ~= können Sie testen, ob sich ein Wert inner- halb eines Bereiches befindet: Als Start- und Endpunkt der Range-Operatoren sind auch String.Index-Elemente erlaubt. s[startindex...endindex] liefert allerdings keine neue Zeichenkette, sondern einen Sub- 1...10 ~= 8 // true ...7 ~= 12 // false String: 7... ~= 12 // true let s = "Hello World!" ...7 ~= 7 // true if let startindex = s.index(of: ""){ ..<7 ~= 7 // false let part1 = s[..

82 83

“buch” — 2017/10/6 — 8:49 — page 84 — #80 “buch”—2017/10/6—8:49—page85—#81

3 Operatoren 3.4 Operatoren für Fortgeschrittene

3.4 Operatoren für Fortgeschrittene Abschnitt 4.2, »Optionals«). Dazu geben Sie explizit den gewünschten Datentyp an, dem wie- derum ein Fragezeichen oder ein Ausrufezeichen folgt: Die wichtigsten Operatoren kennen Sie nun. Dieser Abschnitt ergänzt Ihr Wissen um Spezial- und Hintergrundinformationen. Am interessantesten ist dabei sicherlich die Möglichkeit, var x: Int? = 3 // x enthält eine ganze Zahl oder nil 3 var y: Int! = 4 // y enthält eine ganze Zahl oder nil selbst eigene Operatoren zu definieren bzw. vorhandene Operatoren zu überschreiben (Ope- var z: Int = 5 // z enthält immer eine ganze Zahl rator Overloading). x = nil // ok Ternärer Operator y = nil // ok z = nil // nicht erlaubt Swift kennt drei Typen von Operatoren: Der Unterschied zwischen x und y besteht darin, dass das Auspacken (Unwrapping)des Unäre Operatoren (Unary Operators) verarbeiten nur einen Operanden. In Swift zäh- eigentlichen Werts bei y automatisch erfolgt, während es bei x durch ein nachgestelltes Aus- len dazu das positive und negative Vorzeichen, das logische NICHT (also !bool)unddie rufezeichen – den Unwrapping-Operator – erzwungen werden muss. Beachten Sie, dass die Unwrapping-Operatoren ! und ? zur Auswertung von Optionals (also opt! oder opt?). folgenden Zeilen beide einen Fehler verursachen, wenn x bzw. y den Zustand nil aufweist! Binäre Operatoren verarbeiten zwei Operanden, also etwa das a * b. Die Mehrheit der Swift-Operatoren fällt in diese Gruppe. var i: Int = x! // explizites Unwrapping durch x! var j: Int = y // automatisches Unwrapping Ternäre Operatoren verarbeiten drei Operanden. In Swift gibt es nur einen derartigen Ver- treter, der daher einfach als der ternäre Operator bezeichnet wird – so, als wären andere Die Variablen x und y können also nil enthalten. nil hat eine ähnliche Bedeutung wie bei ternäre Operatoren undenkbar. anderen Sprachen null. Optionals sind aber gleichermaßen für Wert- und für Referenztypen vorgesehen, was in manchen anderen Programmiersprachen nicht oder nur auf Umwegen Die Syntax des ternären Operators sieht so aus: möglich ist. Allerdings können nur solche Klassen für Optionals verwendet werden, die das a?b:c Protokoll ExpressibleByNilLiteral einhalten.

Wenn der boolesche Ausdruck a wahr ist, dann liefert der Ausdruck b,sonstc. Der ternäre Mit diesem Vorwissen kommen wir nun zum Nil-Coalescing-Operator a??b, der sich ebenso Operator eignet sich dazu, einfache if-Verzweigungen zu verkürzen: schwer aussprechen wie übersetzen lässt. Bei ihm handelt es sich um eine Kurzschreibweise des folgenden Ausdrucks: // if-Schreibweise let result:String a!=nil?a!:b let x = 3 Wenn a initialisiert ist, also nicht nil ist, dann liefert a??bden Wert von a zurück, if x<10 { result = "x kleiner 10" andernfalls den Wert von b. Damit eignet sich b zur Angabe eines Defaultwerts. In } else { a! bewirkt das Ausrufezeichen das Auspacken (Unwrapping) des Optionals. Aus dem Optio- result = "x größer-gleich 10" nal Typ? wird also der reguläre Datentyp Typ. } // k den Wert von x oder den Defaultwert -1 zuweisen vark=x??-1 // der Datentyp von k ist Int // verkürzte Schreibweise mit dem ternären Operator let x = 3 let result = x<10 ? "x kleiner 10" : "x größer gleich 10" Optional Chaining

Ebenfalls mit Optionals hat die Operatorkombination ?. zu tun. Sie testet, ob ein Ausdruck Unwrapping- und Nil-Coalescing-Operator nil ergibt. Ist dies der Fall, lautet das Endergebnis nil. Andernfalls wird das Ergebnis aus- Anders als in den meisten anderen Programmiersprachen können mit einem Typ dekla- gepackt und der nächste Ausdruck angewendet. Wenn dieser ebenfalls ein Optional liefert, rierte Swift-Variablen nie den Zustand null im Sinne von »nicht initialisiert« annehmen. kann auch diesem Ausdruck ein Fragezeichen hintangestellt werden. Swift führt einen wei- Swift bietet dafür die Möglichkeit, eine Variable explizit als Optional zu deklarieren (siehe

84 85

“buch”—2017/10/6—8:49—page86—#82 “buch” — 2017/10/6 — 8:49 — page 87 — #83

3 Operatoren 3.5 Eigene Operatoren

teren nil-Test durch. Diese Verkettung von nil-Tests samt Auswertung, wenn der Ausdruck Detailinformationen zu den Prioritätsgruppen sowie weitere Operator-Interna können Sie nicht nil ist, heißt in Swift »Optional Chaining«: im Proposal 0077 nachlesen. Es fasst all die Änderungen zusammen, die in Swift 3 im Bereich der Operatoren durchgeführt wurden und die seither gelten. let a = optional?.method()?.property 3 let b = optional?.method1()?.method2()?.method3() https://github.com/apple/swift-evolution/blob/master/proposals/0077-operator- precedence.md Operator-Präferenz

Beim Ausdruck a+b* c rechnet Swift zuerst b*c aus, bevor es summiert – so wie Sie es in 3.5 Eigene Operatoren der Schule gelernt haben. Generell gilt in Swift eine klare Hierarchie der Operatoren (siehe Tabelle 3.3). Um die Verarbeitungsreihenfolge zu verändern, können Sie natürlich jederzeit Swift bietet Ihnen die Möglichkeit, vorhandenen Operatoren für bestimmte Datentypen Klammern setzen – also beispielsweise (a+b)*c. neue Funktionen zuzuweisen (Operator Overloading). Außerdem können Sie vollkommen neue Operatoren definieren. Priorität Operatoren Operatoren sind aus der Sicht von Swift ein Sonderfall globaler Funktionen, wobei der BitwiseShiftPrecedence << >> Funktionsname aus Operatorzeichen besteht. Insofern greift dieser Abschnitt Kapitel 6, »Funktionen und Closures«, vor. Binäre Operatoren erwarten zwei, unäre Operatoren einen

MultiplicationPrecedence  * /%&* Parameter.

AdditionPrecedence  + - &+ &- | ^

RangeFormationPrecedence ... ..< Reservierte Operatoren Die folgenden Zeichen, Zeichenkombinationen bzw. Operatoren sind reserviert und können CastingPrecedence is as nicht verändert werden: NilCoalescingPrecedence ?? =->///**/.>!? ComparisonPrecedence < <= > >= == != === !=== ~=

LogicalConjunctionPrecedence  && Operator Overloading für komplexe Zahlen

LogicalDisjunctionPrecedence  || Das folgende Beispiel zeigt, wie einfach Operator Overloading ist. Im Beispiel wird zuerst die Datenstruktur Complex zur Speicherung komplexer Zahlen mit Real- und Imaginärteil DefaultPrecedence (keine zugeordneten Operatoren) definiert. Die weiteren Zeilen zeigen die Implementierung der Operatoren + und * zur Ver-

TernaryPrecedence  ?: arbeitung solcher Zahlen.

AssignmentPrecedence  = *= /= %= += -= <<= >>= &= ^= |= &&= ||= // Beispieldatei operator-overloading.playground // Datenstruktur zur Speicherung komplexer Zahlen

FunctionArrowPrecedence  -> struct Complex { var re: Double Tabelle 3.3 Hierarchie der binären Operatoren var im: Double

In Swift gibt es vordefinierte Prioritätsgruppen (Precedence Groups). Die erste Spalte der // Init-Funktion, um eine neue komplexe Zahl zu erzeugen Operatorentabelle gibt neben dem Namen der Gruppe auch die Assoziativität an (soweit init(re: Double , im: Double) { definiert). Diese bestimmt, ob gleichwertige Operatoren von links nach rechts oder von self.re=re rechts nach links verarbeitet werden sollen. Beispielsweise ist - (Minus) ein linksassoziati- self.im=im ver Operator. Die Auswertung erfolgt von links nach rechts. 17-5-3wird also in der Form } } (17 - 5)- 3 verarbeitet und ergibt 9. Falsch wäre 17 - (5 - 3) = 15!

86 87

“buch” — 2017/10/6 — 8:49 — page 88 — #84 “buch”—2017/10/6—8:49—page89—#85

3 Operatoren 3.5 Eigene Operatoren

// Addition komplexer Zahlen zwei Operanden. Der Operator =~= erhält dieselbe Priorität wie die anderen Vergleichsopera- func + (left: Complex, right: Complex) -> Complex { toren. return Complex(re: left.re + right.re, im: left.im + right.im) } // Datei comparision-operator.swift 3 // neuen Vergleichsoperator definieren, ... // Multiplikation komplexer Zahlen infix operator =~= : ComparisonPrecedence func * (left: Complex, right: Complex) -> Complex { Die Implementierung greift auf die compare-Methode zurück. Besser lesbar, aber weniger effi- return Complex(re: left.re right.re - left.im right.im, * * zient wäre return left.uppercased()== right.uppercased(). im: left.re * right.im + left.im * right.re) } // ... implementieren , func =~= (left: String , right: String) -> Bool { // Vergleich komplexer Zahlen return left.compare(right, options: .caseInsensitive) == .orderedSame func == (left: Complex, right: Complex) -> Bool { } return left.re == right.re && left.im == right.im } // ... und ausprobieren func != (left: Complex, right: Complex) -> Bool { "abc" =~= "Abc" // true return !(left==right) "äöü" =~= "ÄöÜ" // true } Neuer Exponential-Operator in einer eigenen Prioritätsgruppe // Operatoren anwenden var a = Complex(re: 2, im: 1) // 2 + i Sie sind bei der Definition eigener Operatoren nicht auf die vorgegebenen Prioritätsgrup- var b = Complex(re: 1, im: 3) // 1 + 3i pen beschränkt. Das folgende Beispiel greift eine Idee aus dem schon erwähnten Proposal varc=a+b // 3 + 4i 0077 auf und definiert den Exponential-Operator ** für Double-Zahlen. Der Operator wird var d = a * b // -1 + 7i der ebenso neuen Gruppe ExponentiationPrecedence zugeordnet. Diese Gruppe hat eine Bei der Definition unärer Operatoren muss mit dem Schlüsselwort prefix bzw. postfix höhere Priorität als MultiplicationPrecedence, mehrere aufeinanderfolgende Exponential- angegeben werden, ob der Operator vor oder nach dem Operanden angegeben wird. Die Defi- Operatoren werden von links nach rechts verarbeitet. nition des Operators für negative Vorzeichen bei komplexen Zahlen sieht so aus: // Datei comparision-operator.swift // negatives Vorzeichen für komplexe Zahlen prefix func - (op: Complex) -> Complex { // neue Prioritätsgruppe für Exponential-Operatoren return Complex(re: -op.re, im: -op.im) precedencegroup ExponentiationPrecedence { } associativity: left higherThan: MultiplicationPrecedence // Anwendung } var e = -d // 1 - 7i // neuer Exponential-Operator infix operator ** : ExponentiationPrecedence Neuer Vergleichsoperator für Zeichenketten Für aktuell nicht genutzte Zeichenkombinationen können Sie selbst neue Operatoren defi- // Implementierung func (base: Double , exponent: Double) -> Double { nieren. Dazu müssen Sie den Operator mit infix|prefix|postfix operator zuerst definieren ** return pow(base, exponent) und einer Prioritätsgruppe zuordnen (siehe Tabelle 3.3). Wenn Sie darauf verzichten, zählt Ihr } Operator automatisch zur Gruppe DefaultPrecedence.

Das folgende Beispiel definiert einen Vergleichsoperator für Zeichenketten, der nicht zwi- let result = 1 + 2 ** 3 // 1 plus (2 hoch 3), Ergebnis 9 schen Groß- und Kleinschreibung unterscheidet. infix bezeichnet dabei einen Operator für

88 89

“buch” — 2017/10/6 — 8:49 — page 90 — #86 “buch”—2017/10/6—8:49—page91—#87

3 Operatoren 3.5 Eigene Operatoren

Neuer Unwrap-or-Die-Operator In Abschnitt 7.3, »CGFloat, CGPoint, CGSize und Co.«, zeige ich Ihnen, wie Sie Operatoren definieren, um bequem Berechnungen mit Koordinatenpunkten, Vektoren etc. durchzu- Erica Sadun hat in der Swift-Evolution-Mailing-Liste vorgeschlagen, die Sprache Swift um den führen. Operator !! zu erweitern, der das Auspacken eines Optionals erzwingt. Gelingt dies nicht, 3 wird ein Fehler ausgelöst. Die Anwendung dieses Operators sieht so aus: In Abschnitt 8.5, »Zeichenketten und Zahlen umwandeln«, stelle ich Ihnen einen Dreizei- ler vor, der den aus Python bekannten Operator % zur Formatierung von Zeichenketten let result = [1, 2, 3] definiert. let firstresult = result.first !! "Fehlermeldung" In Abschnitt 11.5, »Methoden«, habe ich in einem Beispiel, das den Unterschied zwischen print(firstresult) verschiedenen Methodentypen zeigt, auch die Operatoren < und > definiert. Sie ermitteln, Es gibt also einen optionalen Ausdruck (hier first,liefertnil, wenn das Array leer ist), und welcher von zwei 3D-Vektoren kürzer ist. Ihr Code verlässt sich darauf, dass der Ausdruck ein Ergebnis liefert. Sie könnten nun einfach durch first! das Auspacken erzwingen; sollte aber doch ein Fehler auftreten, dann haben Sie keine Fehlermeldung. Mit der Konstruktion !! "Fehlermeldung" können Sie hingegen auf die Ursache des Problems hinweisen. (Der Operator !! ist Ausdrucks des Frusts, den viele Swift-Entwickler im Umgang mit Optionals und der erforderlichen Absicherung durch guard, if let etc. empfinden. Mehr Informationen zu diesem Thema folgen in Abschnitt 4.2, »Optio- nals«, sowie in Kapitel 13, »Fehlerabsicherung«.) Die Swift-Entwicklergemeinde hat sich nicht dazu durchringen können, den Operator zum Swift-Sprachumfang hinzuzufügen. Aber das können Sie mit wenigen Zeilen selbst erledigen:

// Projekt unwrap -or-die-operator, Datei main.swift infix operator !!: NilCoalescingPrecedence extension Optional { // Idee: Erica Sadun 2017 public static func !!(optional: Optional, errorMessage: @autoclosure () -> String) -> Wrapped { if let value = optional { return value } fatalError(errorMessage()) } }

Details zur Implementierung dieses Operators sowie die Diskussion in der Mailing-Liste samt einiger alternativer Vorschläge für ähnlich geartete Operatoren finden Sie hier:

https://gist.github.com/erica/423e4b1c63b95c4c90338cdff4939a9b https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170626/thread.html

Weitere Beispiele für eigene Operatoren In diesem Buch zeige ich Ihnen in mehreren Abschnitten, wie Sie eigene Operatoren gewinn- bringend zur Formulierung klareren Codes definieren können:

90 91

“buch” — 2017/10/6 — 8:49 — page 373 — #369

Kapitel 15 Hello iOS-World!

Mit diesem Kapitel beginnt nun endlich die konkrete iOS-Programmierung. In seinem Zentrum steht ein einfaches Hello-World-Programm. Das Ziel ist es, Sie mit den Grundfunk- tionen von Xcode sowie mit einigen Konzepten der iOS-Programmentwicklung bekannt zu machen. Bei der Lektüre dieses und auch des nächsten Kapitels werden Sie feststellen, dass Swift vor- übergehend in den Hintergrund rückt. Natürlich müssen Sie da und dort ein paar Zeilen Code schreiben; aber gerade bei den ersten iOS-Programmen geht es vielmehr darum, den effizien- ten Umgang mit Xcode zu erlernen, die grafische Gestaltung von Apps kennenzulernen und grundlegende Konzepte der iOS-Programmentwicklung zu verstehen. Dennoch setze ich ab 15 diesem Kapitel voraus, dass Sie zumindest über elementare Grundkenntnisse in Swift verfü- gen. Insbesondere die grundlegenden Sprachstrukturen, Datentypen und der Umgang mit Optionals sollten Ihnen geläufig sein.

Xcode per Video kennenlernen Ich wäre nicht seit 30 Jahren mit Begeisterung Autor, würde ich nicht aus vollster Überzeu- gung das Medium Buch lieben. Aber es heißt ja, ein Bild sagt mehr als tausend Worte, und man könnte diese Analogie noch fortführen: Ein Video sagt mehr als tausend Bilder. Mitunter stimmt das sogar, z. B. wenn es darum geht, die Bedienung von Xcode zu erlernen. Ohne Sie hier an die Konkurrenz verweisen zu wollen, möchte ich Ihnen doch ein Video- Tutorial ans Herz legen, das qualitativ meilenweit über den vielen YouTube-Filmchen der Art »Jetzt lerne ich iOS-Programmierung« steht. Die renommierte Stanford Universität hat eine mehr als 20-stündige Vorlesung zum Thema »Developing iOS 10 Apps with Swift« kostenlos im iTunes U-Programm verfügbar gemacht. Um die Videos ansehen zu können, benötigen Sie entweder iTunes auf Ihrem Mac oder die App iTunesU für das iPad. Grundlegende Englisch- kenntnisse reichen aus, um dem mit vielen Screencasts unterlegten Vortrag zu folgen. Die Videos basieren momentan auf Swift 3.0, es ist aber zu hoffen, dass es 2018 eine aktualisierte Fassung gibt, die iOS 11 und vor allem Swift 4 berücksichtigt. https://itunes.apple.com/us/course/developing-ios-10-apps-with-swift/id1198467120

373

“buch” — 2017/10/6 — 8:49 — page 374 — #370 “buch” — 2017/10/6 — 8:49 — page 375 — #371

15 Hello iOS-World! 15.2 Gestaltung der App

15.1 Projektstart 15.2 Gestaltung der App

Um eine App für ein iOS-Gerät zu entwickeln, also für ein iPhone, ein iPad oder einen iPod, Das neue Projekt besteht aus einer ganzen Reihe von Dateien, deren Namen in der lin- starten Sie in Xcode ein neues Projekt und wählen zuerst den Typ iOS • Single View Appli- ken Spalte von Xcode im Projektnavigator zu sehen sind. Sollte Xcode den Projektnavigator cation. Das ist die einfachste Art von iOS-Apps. Anfänglich besteht eine derartige App aus nicht anzeigen, führen Sie Views • Navigator • Project Navigator aus oder drücken ein- einer einzigen Ansicht, also aus einem »Bildschirm«, aus einer »Seite«. Sie können aber spä- fach (Š)+(1). Im Projektnavigator klicken Sie nun auf die Datei Main.storyboard. ter problemlos weitere Ansichten hinzufügen. Der anfängliche Projekttyp schränkt Sie also Im Hauptbereich von Xcode sehen Sie jetzt das sogenannte Storyboard (siehe Abbildung 15.2). nicht bei der späteren Weiterentwicklung der App ein. Anfänglich besteht dieses Drehbuch für iOS-Apps aus nur einer, vorerst leeren Szene, also Im nächsten Dialogblatt geben Sie Ihrem Projekt einen Namen und wählen als Programmier- einer Bildschirmansicht der App. (Die technische Bezeichnung lautet View-Controller. Details sprache Swift aus. Der Dialog enthält drei Optionen (siehe Abbildung 15.1), die Sie alle drei zur Nomenklatur folgen auf der nächsten Seite.) Bei vielen Apps gesellen sich dazu später wei- nicht aktivieren müssen. (Core Data ist ein Framework, um die App mit einer Datenbank zu tere Seiten, zwischen denen die Anwender dann navigieren können. Im Hello-World-Beispiel verbinden. Die beiden anderen Optionen betreffen automatisierbare Tests.) wird es aber bei einer Ansicht bleiben.

UseCoreDataist nur dann relevant, wenn Sie die Daten Ihrer App in einem Objekt- Relationen-Mapping-Modell speichern möchten. Include Unit Tests und Include UI Tests fügen Ihrem Projekt jeweils ein eigenes Ver- zeichnis hinzu, in dem Sie Testfunktionen für Ihren Code bzw. für die Benutzeroberfläche unterbringen können. 15

Abbildung 15.2 Das Storyboard mit dem einzigen View-Controller der Hello-World-App

Device-Größe Bei neuen iOS-Apps zeigt Xcode die Ansichten der App im Storyboard so an, wie diese auf Abbildung 15.1 Projektoptionen für das Hello-iOS-Projekt einem iPhone 8 im Hochformat aussehen würden. Wenn Sie in der Fußleiste des Storyboard- Editors auf View as iPhone 8 klicken, blendet Xcode eine Auswahl von iOS-Geräten mit Zuletzt müssen Sie noch das Verzeichnis angeben, in dem Xcode die Code-Dateien des neuen anderen Bildschirmformaten ein. Per Knopfdruck können Sie nun zwischen diesen Formaten Projekts speichern soll. wählen (siehe Abbildung 15.2).

374 375

“buch” — 2017/10/6 — 8:49 — page 376 — #372 “buch” — 2017/10/6 — 8:49 — page 377 — #373

15 Hello iOS-World! 15.2 Gestaltung der App

Dieses Feature ermöglicht es Ihnen, blitzschnell zu überprüfen, wie Ihre App auf unterschied- Die Versuchung ist groß, Outlets, Actions, Klassennamen etc. nachträglich zu verändern, lichen Geräten aussehen wird. Anfänglich wird Ihre App nicht auf die unterschiedlichen wenn sich die ursprünglich gewählten Namen als irreführend oder zu wenig prägnant Bildschirmproportionen und -maße reagieren. Abhilfe schaffen sogenannte Layoutregeln, die erweisen. Dabei sollten Sie unbedingt das in Xcode 9 eingeführte Kontextmenükommando ich Ihnen in Abschnitt 15.5, »Layout optimieren«, und detaillierter nochmals in Abschnitt 16.5, Refactor • Rename verwenden, dessen Funktion auch das Storyboard einschließt. Andern- »Auto Layout«, vorstellen werde. falls passen die im Code und die im Storyboard verwendeten Namen nicht mehr zusammen. Ich verwende bei der Entwicklung meiner Apps meistens die Device-Größe »iPhone SE«. Das Abhilfe schafft dann nur das Neuverbinden von Actions und Outlets. Gerade für Xcode- spart einerseits wertvollen Platz im Storyboard-Editor und gibt mir andererseits eine gute Einsteiger ist das schwierig, zumal die wahre Ursache des Problems oft schwer zu erkennen Vorstellung davon, wie die App auf dem kleinsten infrage kommenden Gerät aussehen wird. ist. In der Regel ist die Optimierung für kleine Bildschirme schwieriger als die für große.

Steuerelemente einfügen Mini-Glossar Die Benutzeroberfläche unserer Hello-World-App ist anfänglich leer. In die Ansicht sollen Bevor Sie damit beginnen, die Hello-World-App zu gestalten, sollten Sie zumindest die nun zwei Bestandteile (Steuerelemente) eingebaut werden: ein Button mit der Aufschrift Hello World! Hello World! wichtigsten Grundbegriffe aus der iOS-Entwicklerwelt kennen: Eine App kann aus mehre- und ein leeres Textfeld. Jedes Mal, wenn Sie den Button ankli- ren Ansichten bestehen. Solche Ansichten nennt Xcode Szenen.JedeSzenekanndiverse cken, soll im Textfeld eine neue Zeile mit dem aktuellen Datum und der Uhrzeit eingefügt Steuerelemente enthalten, die das Aussehen der Ansicht bestimmen. Alle Einstellungen aller werden (siehe Abbildung 15.3). Szenen sowie der darin enthaltenen Steuerelemente werden im Storyboard gespeichert. 15 Jede Szene wird mit einer Code-Datei verbunden, dem Controller. Im Controller legen Sie fest, wie Ihre App auf Ereignisse reagiert. Der Controller bestimmt also, wie sich Ihre App verhalten soll, wenn ein Benutzer einen Button berührt, einen Slider verschiebt etc. Das dem Control- ler zugrunde liegende Programmiermuster, den Model-View-Controller, stelle ich Ihnen in Abschnitt 16.1 näher vor.

Standardmäßig enthält ein neues Projekt vom Typ Single View Application die Storyboard- Datei Main.storyboard mit der Szene View-Controller und dem zugeordneten Controller in der Datei ViewController.swift. Um später weitere Szenen hinzuzufügen, verschieben Sie einen View-Controller aus der Xcode-Objektbibliothek in das Storyboard. Während im Storyboard beliebig viele Szenen gespeichert werden können, benötigen Sie im Regel- fall zu jeder Szene eine eigene Swift-Code-Datei mit dem Controller. Mitunter können Sie auch eine Controller-Klasse mehreren ähnlichen Szenen zuordnen. Wie Sie selbst neue Controller-Klassen einrichten, beschreibe ich in Abschnitt 17.1, »Storyboard und Controller- Klassen verbinden«.

Vorsicht bei Umbenennungen! Die grafische Darstellung des Storyboards in Xcode ist sehr ansprechend. Intern handelt es sich beim Storyboard aber um eine simple XML-Datei. Dabei ist es wichtig zu wissen, dass die Referenzen vom Storyboard auf Code-Elemente und Komponenten ausschließlich in Form von Zeichenketten erfolgen. Abbildung 15.3 Die Hello-World-App im iOS-Simulator, hier in der iPhone-X-Ausprägung

376 377

“buch” — 2017/10/6 — 8:49 — page 378 — #374 “buch” — 2017/10/6 — 8:49 — page 379 — #375

15 Hello iOS-World! 15.2 Gestaltung der App

Xcode zeigt die zur Auswahl stehenden Steuerelemente normalerweise rechts unten in der Objektbibliothek an. Sollten die Steuerelemente bei Ihnen nicht sichtbar sein, blenden Sie Spracheinstellungen im Simulator diesen Bereich der Werkzeugleiste mit View • Utilities • Show Object Library bzw. mit Im Simulator gelten anfänglich englische Spracheinstellungen. Das lässt sich wie auf einem (ctrl)+(alt)+(Š)+(3) ein. richtigen Gerät in den Systemeinstellungen beheben. Dazu beenden Sie die laufende Hello- World-App durch einen Klick auf den iPhone-Button (»Home-Button«). Anschließend starten Xcode kann die Objektbibliothek in einer kompakten Icon-Ansicht oder in einer Listen- Sie die vorinstallierte App Settings, navigieren in den Dialog General • Language & Region ansicht darstellen. Wechseln Sie gegebenenfalls mit dem Button am unteren Rand der und stellen dort die Sprache Deutsch und die Region Germany ein. Objektbibliothek in die übersichtlichere Listenansicht. Im daneben befindlichen Suchfeld können Sie in der Liste rasch die gewünschten Einträge ermitteln – suchen Sie nach button Diesen Vorgang müssen Sie für jedes iOS-Gerät wiederholen, das Sie testen möchten. Die bzw. text view. Einstellungen werden also nicht über alle simulierten Geräte geteilt. Da die Veränderung der Spracheinstellungen in allen iOS-Geräten recht umständlich ist, bie- Klicken Sie zuerst den Button an, und verschieben Sie ihn per Drag & Drop in den quadra- tet Xcode auch die Möglichkeit, mit Product • Scheme • Edit Scheme festzulegen, in welcher tischen View-Controller des Storyboards. Platzieren Sie den Button links oben, und ändern Sprache die App ausgeführt werden soll. Das Hello-World-Kapitel ist aber nicht der richtige Sie dann den Text von Button zu Hello World (siehe Abbildung 15.2). Wenn Sie möchten, Ort für diese schon recht fortgeschrittenen Funktionen. Details zum Umgang mit Schemes können Sie im Attributinspektor links oben in der Werkzeugleiste die Button-Schrift etwas und zur Entwicklung mehrsprachiger Apps folgen in Abschnitt 31.4. größer einstellen. Den Attributinspektor blenden Sie bei Bedarf mit (alt)+(Š)+(4) ein.

Nun ist das Text-View-Steuerelement an der Reihe: Suchen Sie in der Objektbibliothek nach Im iOS-Simulator können Sie nun den Button Hello World! anklicken. Das Programm wird diesem Steuerelement, und verschieben Sie es per Drag & Drop in das Storyboard. Platzieren darauf aber nicht reagieren, weil der Button ja noch nicht mit Code verbunden ist. Wenn Sie das Steuerelement unterhalb des Buttons, und stellen Sie die Größe so ein, dass es circa Sie das Textfeld anklicken, können Sie über die Tastatur Ihres Computers sowie über die im 15 ein Viertel des quadratischen Storyboards füllt. Wie gesagt, mit den Feinheiten des Layouts Simulator eingeblendete Bildschirmtastatur Text eingeben. Die Test-App läuft, bis Sie sie in beschäftigen wir uns später. Stellen Sie nun die gewünschte Textgröße ein, und löschen Sie Xcode mit dem Stopp-Button beenden. denBlindtext»Loremipsum...«imAttributinspektor.

WennSiemöchten,könnenSiedemTextfeldauchnocheineandereHintergrundfarbe Ärger mit der Tastatur zuweisen – dann erkennen Sie später bei der Programmausführung besser die tatsächlichen Sie können im iOS-Simulator mit der Tastatur Ihres Computers Eingaben durchführen. Das Ausmaße des Steuerelements. Zur Farbeinstellung scrollen Sie im Attributinspektor nach ist effizient, aber nicht realitätsnah: Der Simulator betrachtet Ihre Tastatur als mit dem iOS- unten, bis Sie relativ weit unten im Bereich View das Feld Background finden. Gerät verbunden und blendet deswegen die iOS-Bildschirmtastatur aus. Mit dem Kommando Hardware • Keyboard • Connect Hardware Keyboard im iOS-Simulator können Sie auswäh- Ein erster Test mit dem iOS-Simulator len, ob Sie Ihre Computertastatur oder die Bildschirmtastatur von iOS verwenden möchten. Nachdem wir nun die minimalistische Oberfläche unserer App gestaltet haben, spricht nichts Sobald die iOS-Bildschirmtastatur einmal im iOS-Simulator erscheint, tritt ein weiteres Pro- dagegen, das Programm ein erstes Mal zu starten. Dazu wählen Sie in der Symbolleiste des blem auf: Es scheint keine Möglichkeit zu geben, die Tastatur wieder loszuwerden. Das ist Xcode-Fensters zuerst das Gerät aus, das Sie simulieren möchten. Zur Auswahl steht die gän- das in iOS vorgesehene Verhalten – wenn die Eingabe abgeschlossen ist, muss die Tasta- gige iOS-Hardware-Palette. tur per Code explizit ausgeblendet werden, in der Regel durch die Anweisung view.end- Editing(true). Im Hello-World-Projekt verzichten wir darauf. Ein Klick auf den dreieckigen Run-Button kompiliert das Programm und übergibt es zur Ausführung an den iOS-Simulator (siehe Abbildung 15.3). Dabei handelt es sich um ein eigen- Praktische Details zum richtigen Umgang mit Textfeldern folgen in Abschnitt 16.9, »Textein- ständiges Programm, das getrennt von Xcode läuft. Wie der Name vermuten lässt, simuliert gaben«, sowie in mehreren Beispielprojekten in Teil IV dieses Buchs. es ein iPhone bzw. iPad, wobei das zu testende Programm zur Ausführung automatisch instal- liert wird. Der Simulator ist zumindest für erste Tests gut geeignet. Für »echte« Apps führt an Tests auf richtiger Hardware aber natürlich kein Weg vorbei.

378 379

“buch” — 2017/10/6 — 8:49 — page 380 — #376 “buch” — 2017/10/6 — 8:49 — page 381 — #377

15 Hello iOS-World! 15.3 Steuerung der App durch Code

15.3 Steuerung der App durch Code Object: Das Feld gibt das Basisobjekt der Aktion an. Die Voreinstellung lautet View Con- troller und bleibt immer unverändert. Damit das Berühren des Buttons auf einem iPhone bzw. das Anklicken des Buttons im Simu- Name: Hier geben wir der zu erstellenden Methode einen möglichst aussagekräftigen lator eine sichtbare Wirkung zeigt, soll die App jetzt so erweitert werden, dass in das Textfeld Namen. Ich habe mich bei diesem Beispiel für hwButtonTouch entschieden. Wenn Sie das jedes Mal eine Zeile mit dem Datum und der aktuellen Uhrzeit eingefügt wird. Das erfordert Beispiel selbst ausprobieren, können Sie hier einen beliebigen anderen Namen wählen. einige Zeilen Swift-Code. Type = AnyObject oder UIButton: Diese Einstellung gibt an, in welcher Form Daten an die Den Button mit einer Methode verbinden (Actions) Methode übergeben werden sollen. Im Hello-World-Beispiel werten wir diese Daten aber ohnehin nicht aus – insofern ist die Einstellung egal. Wollten wir den Text des Buttons MitderApp-Ansicht(Szene) verbundener Code muss nun in die bereits vorgesehene Datei oder andere Eigenschaften auslesen, wäre es zweckmäßig, hier UIButton einzustellen. ViewController.swift eingetragen werden. Xcode unterstützt diesen Vorgang, sofern das Event = Touch Up Inside: Hier wird festgelegt, auf welches Ereignis wir reagieren möch- Storyboard und die damit verbundene Datei ViewController.swift nebeneinander angezeigt ten. Die Defaulteinstellung passt hier: Wenn der Button innen berührt wird, soll unser werden. Genau das bewirkt der Button mit den »Eheringen«: Er blendet zur gerade aktiven Code ausgeführt werden. Datei den sogenannten Assistenzeditor ein, also eine zugeordnete zweite Datei. Arguments = Sender: In der Auswahlliste können Sie festlegen, welche Daten an die Methode übergeben werden sollen. Zur Auswahl stehen Sender, Sender and Event oder Platz sparen in Xcode None. Die Einstellung Sender bedeutet, dass eine Referenz auf das Objekt übergeben wird, Wenn Sie nicht gerade auf einem sehr großen Monitor arbeiten, wird der Platz in Xcode das die Aktion ausgelöst hat. Das vereinfacht die Auswertung der Daten dieses Objekts – jetzt knapp. Links sitzt der Projektnavigator, in der Mitte das Storyboard und der Code des insbesondere dann, wenn Sie eine Action-Methode mit mehreren Steuerelementen ver- 15 Controllers und rechts noch die Werkzeugleiste – das ist zu viel! Blenden Sie deswegen vor- binden. übergehend die beiden Seitenleisten aus. Die entsprechenden Buttons finden Sie rechts oben in der Xcode-Symbolleiste.

ViewController.swift enthält den Swift-Code für eine Klasse mit dem Namen ViewController. Diese Klasse ist von der UIViewController-Klasse abgeleitet. Wie der Name vermuten lässt, steuert diese Klasse das App-Erscheinungsbild. Der View-Controller enthält bereits zwei leere Methoden. Diese sind für uns vorerst aber nicht von Interesse; wenn Sie möchten, können Sie sie löschen. In diesem Hello-World-Beispiel benötigen wir sie nicht.

Dafür möchten wir nun eine Methode in den Code einbauen, die ausgeführt wird, wenn der Button Hello World angeklickt wird. Dazu drücken Sie die Taste (ctrl) und ziehen den Button vom Storyboard in den Assistenzeditor. Die Methode soll direkt in der Klasse und nicht innerhalb einer anderen Methode eingefügt werden. Achten Sie darauf, die Maus- bzw. Trackpad-Taste an der richtigen Stelle loszulassen! Bis dahin markiert eine blaue Linie die Verbindung, die Sie herstellen möchten. Sobald Sie die Maus bzw. das Trackpad losgelassen haben, erscheint ein Dialog, in dem Sie die Details der Verbindung einstellen können (siehe Abbildung 15.4). Für uns sind folgende Einstellungen zweckmäßig:

Connection = Action: Wir wollen auf ein Ereignis reagieren. Der Begriff Action bezieht sich dabei auf das Target-Action-Entwurfsmuster, bei dem eine Methode in die eigene Abbildung 15.4 Der Button des Storyboards (links) wird durch ctrl-Drag mit einer neuen Methode Controller-Klasse eingebaut wird. Sie gilt als »Ziel«, das angesprungen wird, wenn das ent- im ViewController-Code (rechts) verbunden. sprechende Ereignis auftritt.

380 381

“buch” — 2017/10/6 — 8:49 — page 382 — #378 “buch” — 2017/10/6 — 8:49 — page 383 — #379

15 Hello iOS-World! 15.3 Steuerung der App durch Code

Die hier so langatmig beschriebenen Einstellungen nehmen Sie mit etwas Übung in gerade mal 15 Sekunden vor. Xcode belohnt diese Arbeit mit einer Methodendefinition, die aus zwei Zeilen Code besteht:

// Projekt hwios-world, Datei ViewController.swift @IBAction func hwButtonTouch(_ sender: UIButton) { // todo: Code verfassen }

Abbildung 15.5 Einstellungen für das textView-Outlet Der Code allein reicht nicht! Angesichts des doch recht umständlichen Mausgeklickes liegt es nahe, den wenigen Code Die resultierende Code-Zeile sieht so aus: einfach selbst einzutippen. Das ist aber keine gute Idee! Mit dem Code an sich ist es näm- @IBOutlet weak var textView: UITextView! lich nicht getan. Hinter den Kulissen merkt sich Xcode auch, mit welchem Steuerelement und mit welchem Ereignis die Methode verknüpft ist. Diese Metadaten landen in der XML-Datei Damit ist also eine neue Eigenschaft (Klassenvariable) mit dem Namen textView definiert. Main.storyboard. Die Verbindung stellt Cocoa Touch dynamisch zur Laufzeit her. Das kompi- Wir können mit ihr auf ein Steuerelement vom Typ UITextView zugreifen, wobei der Typ lierte Storyboard enthält dafür eine Referenz auf den serialisierten View-Controller und den als Optional angegeben ist. Der Grund dafür ist, dass die Initialisierung des Steuerelements Selektor auf die Methode. möglicherweise nicht sofort beim App-Start, sondern erst etwas später erfolgt. Indem die Eigenschaft als Optional deklariert ist, wird klar, dass ein Zugriff auf das Steuerelement unter Umständen noch gar nicht möglich ist. 15 Zugriff auf das Textfeld über eine Eigenschaft (Outlets)

Bevor wir die Methode hwButtonTouch mit konkretem Code füllen können, benötigen wir Die Attribute »@IBAction« und »@IBOutlet« noch eine Möglichkeit, um auf das Textfeld zuzugreifen. Dazu stellen wir eine weitere Verbin- Sicher ist Ihnen aufgefallen, dass Xcode die Methode mit dem Attribut @IBAction und die (ctrl) dung zwischen der App-Ansicht im Storyboard und dem Code her: Wieder mit ziehen Eigenschaft mit dem Attribut @IBOutlet gekennzeichnet hat. Der Interface Builder erkennt wir diesmal das Text-View-Steuerelement in den Codebereich, verwenden diesmal aber anhand dieser Attribute, zu welchen Elementen der Programmierer Verbindungen erlaubt andere Einstellungen (siehe Abbildung 15.5): bzw. herstellen darf. Der Interface Builder ist jener Teil von Xcode, der zur Gestaltung grafi- Connection = Outlet: Wir wollen auf das Steuerelement zugreifen können. Xcode soll scher Benutzeroberflächen dient. also eine entsprechende Eigenschaft in die ViewController-Klasse einbauen, die auf das Objekt verweist. In der iOS-Nomenklatur wird das als Outlet bezeichnet. Endlich eigener Code Object: Das Feld gibt das Basisobjekt der Aktion an. Die Voreinstellung View Controller Sie können die App zwischenzeitlich noch einmal starten. Am Verhalten der App hat sich aber kann nicht geändert werden. nichts verändert. Die Methode hwButtonTouch ist ja noch leer, und auch die zusätzliche Eigen- Name: Das ist der Name, unter dem wir das Steuerelement ansprechen möchten. Ich habe schaft textView ist noch ungenutzt. Aber das ändert sich jetzt endlich! Jedes Mal, wenn der textView angegeben. Button Hello World berührt wird, soll das Textfeld um eine Zeile mit Datum und Uhrzeit Type = UITextView: Das Steuerelement ist eine Instanz der UITextView-Klasse – und unter ergänzt werden. In einer ersten Testversion könnte der Code wie folgt aussehen: diesem Typ möchten wir auf das Steuerelement auch zugreifen. // Projekt Hello iOS, Datei ViewController.swift Storage = Weak: Hier geht es darum, ob die Referenz auf das Steuerelement sicherstellt, import UIKit dass dieses im Speicher bleibt. Das ist nicht notwendig: Das Steuerelement kommt uns class ViewController: UIViewController { sicher nicht abhanden. Insofern können wir die Defaulteinstellung Weak bedenkenlos @IBOutlet weak var textView: UITextView! übernehmen.

382 383

“buch” — 2017/10/6 — 8:49 — page 384 — #380 “buch” — 2017/10/6 — 8:49 — page 385 — #381

15 Hello iOS-World! 15.4 Actions und Outlets für Fortgeschrittene

@IBAction func hwButtonTouch(_ sender: UIButton) { let now = Date()

// zur Formattierung des Datums let formatter = DateFormatter() formatter.dateFormat = "d.M.yyyy H:mm:ss"

// Text im Text-View-Steuerelement hinzufügen textView.text? += formatter.string(from: now) + "\n" } }

Auf den Abdruck der standardmäßig vorhandenen, aber leeren Methoden viewDidLoad und didReceiveMemoryWarning habe ich verzichtet. In diesem Beispiel können Sie diese Methoden aus dem Code löschen, wir brauchen sie nicht.

Outlets wie die Eigenschaft textView sind Optionals. Es liegt in der Natur von Optionals, dass diese den Zustand nil haben können. Tatsächlich ist dies aber nur vor der Initialisierung der Ansicht der Fall. Sobald die Ansicht auf einem iOS-Gerät sichtbar wird und Action-Methoden Abbildung 15.6 ausführen kann, können Sie sich darauf verlassen, dass Outlet-Eigenschaften nicht nil sind. Der Hilfebrowser von Xcode Genau genommen gilt dies ab dem Zeitpunkt, zu dem im View-Controller die Methode 15 viewDidLoad ausgeführt wurde (siehe Abschnitt 16.3, »Die UIViewController-Klasse«). 15.4 Actions und Outlets für Fortgeschrittene

Hintergrundinformationen zum Umgang mit Datum und Uhrzeit können Sie bei Bedarf in Sie haben nun eine erste Vorstellung davon, wozu Actions und Outlets verwendet werden. Kapitel 9 nachlesen. Somit bleibt nur noch der Ausdruck textView.text zu erklären: Ein Blick Dieser Abschnitt weist auf einige Besonderheiten im Umgang mit Actions und Outlets hin. in die Dokumentation des UITextView-Steuerelements zeigt, dass der Inhalt des Textfelds über die Eigenschaft text gelesen und verändert werden kann. Der Datentyp von text lautet Eine Action für mehrere Steuerelemente String?, es handelt sich also um ein Optional, das beim Zugriff explizit durch ein nachgestell- tes Fragezeichen oder Ausrufezeichen ausgepackt werden muss. Es ist zulässig, ein und dieselbe Action-Methode für mehrere Steuerelemente zu verwenden. Dazu richten Sie zuerst für ein Steuerelement die Methode ein. Danach führen Sie eine (ctrl)- Drag-Operation für das zweite Steuerelement aus, wobei Sie als Ziel die bereits vorhandene Der schnellste Weg zur Dokumentation Methode verwenden. Achten Sie darauf, dass die gesamte Methode blau unterlegt wird – Wenn Sie zum ersten Mal ein UITextView-Steuerelement nutzen, kennen Sie die Elemente dann hat Xcode erkannt, dass Sie nicht eine Action in der Methode einfügen möchten (das dieser Klasse noch nicht. Eine kurze Beschreibung der Klasse erhalten Sie, wenn Sie das funktioniert nicht), sondern dass Sie das Steuerelement mit der vorhandenen Methode ver- Schlüsselwort UITextView im Code zusammen mit (alt) anklicken. Am unteren Rand der ein- binden möchten. geblendeten Infobox befindet sich ein Link auf die Klassenreferenz, die in einem eigenen Naturgemäß müssen Sie die Methode nun ein wenig modifizieren: Erst mit einer Auswer- Fenster geöffnet wird (siehe Abbildung 15.6). tung des sender-Parameters können Sie erkennen, welches Steuerelement den Aufruf der Methode ausgelöst hat. Wenn Sie beispielsweise mehrere Buttons mit einer Methode verbun- Jetzt ist es höchste Zeit, die App im Simulator endlich auszuprobieren. Einige Klicks auf den den haben, können Sie wie folgt den Text des Buttons ausgeben: Button beweisen, dass das Programm wie erwartet funktioniert (siehe Abbildung 15.3). Einen Preis für innovatives Layout wird es freilich nicht gewinnen. @IBAction func btnAction(_ sender: UIButton) { print(sender.currentTitle!) }

384 385

“buch” — 2017/10/6 — 8:49 — page 386 — #382 “buch” — 2017/10/6 — 8:49 — page 387 — #383

15 Hello iOS-World! 15.4 Actions und Outlets für Fortgeschrittene

Ein Outlet für mehrere Steuerelemente (Outlet Collections) Auch der umgekehrte Fall ist möglich – Sie können mehrere Steuerelemente über ein Outlet ansprechen. Genau genommen handelt es sich dann nicht mehr um ein einfaches Outlet, sondern um eine Outlet Collection. Dazu markieren Sie das erste Steuerelement, ziehen es mit (ctrl)-Drag in den Controller-Code und wählen Connection = Outlet Collection (siehe Abbildung 15.7). Xcode erzeugt anstelle einer einfachen Outlet-Variablen nun ein Array:

@IBOutlet var allButtons: [UIButton]!

In der Folge verbinden Sie auch die weiteren Steuerelemente durch (ctrl)-Drag mit die- sem Array. Xcode ist leider nicht in der Lage, mehrere markierte Steuerelemente auf einmal zu verbinden. Im Code können Sie nun unkompliziert Schleifen über alle so verbundenen Steuerelemente bilden.

Abbildung 15.8 Umbenennung einer Outlet-Variablen

Wesentlich hilfreicher ist Xcode in die umgekehrte Richtung: Wenn Sie im Storyboard-Editor das betreffende Steuerelement mit der rechten Maus- oder Trackpad-Taste anklicken, zeigt ein Kontextmenü alle Zuordnungen zu Actions oder Outlets (siehe Abbildung 15.9). Dort kön- 15 nen Sie die Action- oder Outlet-Verknüpfung löschen, die Sie nicht mehr brauchen. Abbildung 15.7 Dialog zum Einrichten einer Outlet-Collection

Actions oder Outlets umbenennen Wenn Sie im Code Actions oder Outlets einfach einen neuen Namen geben, funktioniert Ihre App nicht mehr. Xcode merkt sich die Verknüpfung zu Ihren Methoden bzw. Eigenschaften in Form von Zeichenketten. Nach der Umbenennung ist dann keine korrekte Zuordnung mehr möglich. Deswegen müssen Sie zum Umbenennen das neu in Xcode 9 verfügbare Kommando Refac- tor • Rename verwenden. Sie können dieses Kommando entweder nach einem Kontext- menüklick auf den Variablennamen oder über das Editor-Menü ausführen. Xcode zeigt nun automatisch alle Stellen im Code und im Storyboard an, wo die Umbenennung wirksam wird (siehe Abbildung 15.8).

Zuordnung zwischen Steuerelementen und Actions/Outlets ergründen Eigenschaften und Methoden, die mit Steuerelementen verbunden sind, werden im Code- Editor durch einen runden Punkt gekennzeichnet. Der Editor verrät aber leider nicht, zu welchem Steuerelement die Verbindung besteht. Abbildung 15.9 Die rechte Maus- oder Trackpad-Taste führt in eine Liste aller Actions und Outlets eines Steuerelements.

386 387

“buch” — 2017/10/6 — 8:49 — page 388 — #384 “buch” — 2017/10/6 — 8:49 — page 389 — #385

15 Hello iOS-World! 15.5 Layout optimieren

element Regeln aufstellen, die das Steuerelement einhalten soll. Das UIKit bemüht sich dann, Fehlermeldung »unrecognized selector« in Abhängigkeit von der gerade vorliegenden Form und Größe des iOS-Geräts, allen Regeln Wenn Ihre App mit der nicht besonders aussagekräftigen Fehlermeldung unrecognized selec- gerecht zu werden. Beispiele für derartige Regeln sind: tor abstürzt, liegt dies in der Regel daran, dass die Zuordnung zwischen einem Steuerelement Der horizontale Abstand zwischen dem Steuerelement A und seinem nächstgelegenen und dem Outlet oder der Action verloren gegangen ist – z. B. weil Sie einen Action-Methoden- linken oder rechten Nachbarn soll 8 Punkte betragen. Bei Retina-Geräten mit doppelter namen direkt geändert haben, anstatt Refactor • Rename auszuführen. Auflösung entspricht das 16 Pixeln. Abhilfe: Löschen Sie im Kontextmenü die Verbindung (siehe Abbildung 15.9), und richten Sie Der vertikale obere Abstand zwischen dem Steuerelement A und dem Bildschirmrand soll diese dann mit einem (ctrl)-Drag neu ein. 16 Punkt betragen. Steuerelement A soll genauso breit sein wie Steuerelement B. Steuerelemente kopieren Steuerelement A soll innerhalb seines Containers vertikal und/oder horizontal zentriert Wenn Sie Steuerelemente mit (Š)+(C) und (Š)+(V) kopieren, werden dabei alle möglichen un- werden. sichtbaren Attribute und Eigenschaften mitkopiert, unter anderem zugeordnete Actions. Oft Die linken Ränder der Steuerelemente A, B und C sollen in einer Linie verlaufen. erspart Ihnen das eine wiederholte Einstellung dieser Merkmale, aber mitunter führt dieses Verhalten zu unerwarteten Nebenwirkungen. Ein Klick auf das Steuerelement mit der rechten Wenn wir also erreichen möchten, dass die Steuerelemente der Hello-World-App wie oben Maus- oder Trackpad-Taste offenbart alle zugeordneten Outlets und Actions. formuliert angeordnet werden, müssen wir nur die entsprechenden Regeln formulieren. Mit etwas Erfahrung gelingt dies rasch; gerade Einsteiger in die iOS-Programmierung scheitern aber oft an der damit verbundenen Komplexität. 15 15.5 Layout optimieren Glücklicherweise macht Xcode es sehr einfach, Layoutregeln zu testen, ohne die App jedes Mal neu starten zu müssen: Dazu verändern Sie einfach in der Fußleiste von Xcode das iOS- Es ist Ihnen sicher aufgefallen, dass das Layout unserer App, also die Anordnung und Größe Device und seine Orientierung. Xcode passt dann die View an die neue Gerätegröße an, und der Steuerelemente, verbesserungswürdig ist. Die Größe der Steuerelemente ist willkürlich. Sie erkennen sofort, ob die Steuerelemente wunschgemäß platziert werden. Wenn Sie die App in verschiedenen iOS-Geräten ausprobieren, werden Sie feststellen, dass teilweise große Teile des Bildschirms ungenutzt bleiben, während das Textfeld bei anderen Layoutregeln für den »Hello-World«-Button Geräten womöglich sogar abgeschnitten und unvollständig dargestellt wird. Besonders deut- lich werden die Layoutdefizite, wenn Sie den iOS-Simulator mit Hardware • Rotate in das Eine detaillierte Erklärung der Layoutregeln erhalten Sie in Abschnitt 16.5, »Auto Layout«. Querformat drehen. An dieser Stelle möchte ich Ihnen nur rezeptartig erklären, wie Sie das Layout der Hello- World-App korrekt einstellen. Um die Layoutregeln einzustellen, verwenden Sie fünf Buttons, Wie würden unsere Layoutwünsche denn aussehen? die sich rechts unten im Editor befinden (siehe Abbildung 15.10). Die ersten beiden Buttons Der Button soll ohne unnötige Abstände links oben im Bildschirm dargestellt werden. (Update Frames und Embed in Stack) lösen unmittelbar Aktionen aus. Die anderen drei Das Textfeld soll darunter platziert sein. führen in kleine Dialoge bzw. Menüs, in denen Sie Einstellungen vornehmen können. Es soll die gesamte verbleibende Größe des Bildschirms nutzen. Es soll seine Größe bei einer Drehung des Geräts automatisch anpassen. Momentan wird unser Programm diesen Wünschen deswegen nicht gerecht, weil wir die Position und Größe der Steuerelemente absolut festgelegt haben. Wir haben die Steuer- elemente im View weitgehend nach Gutdünken platziert.

Layoutregeln Die Lösung, die Xcode bzw. eigentlich das UIKit (also das Framework zur iOS-Programmie- Abbildung 15.10 Die winzigen Layout-Buttons befinden sich rechts unten im Storyboard-Editor. rung) hierfür anbietet, heißt Layoutregeln (Constraints). Sie können also für jedes Steuer-

388 389

“buch” — 2017/10/6 — 8:49 — page 390 — #386 “buch” — 2017/10/6 — 8:49 — page 391 — #387

15 Hello iOS-World! 15.5 Layout optimieren

BeginnenSiemitdemButtonHello World!: Nachdem Sie den Button beschriftet haben, Interessant ist das Verhalten, wenn Sie den Button aus seiner durch die Regeln festgeleg- platzieren Sie ihn links oben im View Controller, wobei Sie Abstände zu den Rändern einhal- ten Position hinausziehen. Nun zeigen orange strichlierte Linien an, wo der Button bei der ten. Dabei helfen Orientierungslinien, an denen der Button beim Verschieben einrastet. Den Programmausführung platziert wird (siehe Abbildung 15.12). Außerdem visualisieren zwei rechten Rand des Buttons ziehen Sie bis knapp an den rechten Rand des View Controllers. orange Stege die von Ihnen aufgestellten Regeln. Aus den Zahlenwerten geht hervor, um Auch dort rastet der Button ein. Damit nutzt der Button die gesamte Breite, hält dabei aber wie viele Punkte das Element aktuell falsch positioniert ist. Um den Button den Regeln ent- einen kleinen optischen Abstand ein und lässt die obere Zeile des iPhones oder iPads frei. sprechend wieder korrekt zu positionieren, klicken Sie auf den ersten Layout-Button Update Damit der Text dennoch links ausgerichtet wird, stellen Sie die Textausrichtung im Attribut- Frames. inspektor auf Alignment = Left. Während der Button noch immer ausgewählt ist, klicken Sie nun auf den Layout-Button Add New Constraints. Damit erscheint der gleichnamige Dialog zur Einstellung diver- ser Abstände (siehe Abbildung 15.11). Dort klicken Sie zuerst die Verbindungsstege für die Abstände nach oben, nach links und nach rechts an, sodass diese Stege durchgängig rot ange- zeigt werden. Alle drei Abstandswerte sollten jeweils den Wert 0 enthalten. Standardmäßig ist Constrain to margins die Option aktiv. Sie bewirkt, dass diese Abstände relativ zu den vom Abbildung 15.12 Wenn die Position eines Steuerelements aktuell nicht den Layoutregeln entspricht, jeweiligen iOS-Gerät vorgegebenen Rahmen (Guide Lines) gerechnet werden. Zuletzt schlie- zeigt der Storyboard-Editor an, wo das Element zur Laufzeit platziert wird. ßen Sie den Dialog mit dem Button Add 3 Constraints. Damit werden drei neue Regeln zur Positionierung des Buttons festgelegt. Layoutregeln für das Textfeld 15 Nun ist das Textfeld an der Reihe. Der erste Schritt besteht wieder darin, dass Sie das Steuer- element in der Ansicht so platzieren, wie es auch zur Laufzeit angeordnet werden soll. In diesem Fall bietet es sich an, das Steuerelement bündig unterhalb des Buttons anzuord- nen und dann die Größe so einzustellen, dass es – wieder unter Einhaltung eines kleinen Abstands – den ganzen View-Controller ausfüllt. Das fällt nicht schwer, weil die Begrenzungs- linien des Steuerelements automatisch an den richtigen Stellen einrasten. Nun klicken Sie neuerlich auf den Button Add New Constraints. Dort stellen Sie die folgen- den Abstände ein (siehe Abbildung 15.13):

Links: 0 Punkte. Dieser Abstand gilt wegen der Option Constrain to margins relativ zum Standardrahmen. Oben: 8 Punkte. Dieser Abstand wird relativ zum nächstgelegenen Steuerelement gerech- net, in diesem Fall also zum Button. Rechts: 0 Punkte. Dieser Abstand gilt wieder relativ zum Standardrahmen. Unten: 8 Punkte. Auch dieser Abstand gilt relativ zum Standardrahmen. Dieser sieht nach Abbildung 15.11 Layoutregeln für den Hello-World-Button festlegen unten aber keinen Rand vor. Damit das Textfeld von allen Rändern gleich weit entfernt ist, muss hier ein etwas größerer Wert angegeben werden. Die neuen Layoutregeln ändern nichts an der aktuellen Position des Buttons. Sie können Add 4 Constraints beendet die Eingabe und fügt vier Regeln hinzu. Damit sollten beide View as iPhone xxx nun aber versuchen, in der Leiste ein anderes Gerät auszuwählen. Steuerelemente korrekt angeordnet sein. Ändern Sie nun in der Fußleiste des Storyboard- Aufgrund der Layoutregeln wird sich der Button automatisch an die geänderten Platzverhält- Editors das iOS-Device und die Ausrichtung. Der Ort und die Größe der Steuerelemente sind nisse anpassen. nun immer korrekt an die jeweilige Bildschirmgröße angepasst (siehe Abbildung 15.14).

390 391

“buch” — 2017/10/6 — 8:49 — page 392 — #388 “buch” — 2017/10/6 — 8:49 — page 393 — #389

15 Hello iOS-World! 15.5 Layout optimieren

15

Abbildung 15.14 Die Hello-World-App im iPhone-8-Querformat

Abbildung 15.13 Layoutregeln für das Textfeld

Embed-in-Stack-Aktion rückgängig machen Die Buttons Align, Add New Constraints und Resolve Auto Layout Issues führen jeweils in Dialoge oder Menüs, in denen Sie die jeweilige Aktion auswählen bzw. bestätigen. Es besteht also keine Gefahr, dass Sie irrtümlich eine Aktion durchführen, die Sie nicht wollen. Ganz anders verhält sich der zweite Layout-Button Embed in Stack: Sofern im Storyboard- Editor gerade ein Steuerelement markiert ist bzw. mehrere Steuerelemente markiert sind, werden diese in eine Stack-View verpackt, also in einen Container, der bei der Anordnung der Steuerelemente helfen soll. Diese Aktion erfolgt sofort, ohne Rückfrage und ohne visuelles Feedback, also oft ungewollt und unbemerkt. Ungewollte Stack-View-Verschachtelungen erkennen Sie, wenn Sie im Storyboard-Editor die Seitenleiste Document Outline aktivieren. Sie zeigt die hierarchische Struktur aller Steuer- elemente im Storyboard-Editor. Dort können Sie bei Bedarf die betroffenen Steuerelemente Abbildung 15.15 Ungewollte Stack-View-Verschachtelungen auflösen aus der Stack-View herausziehen (siehe Abbildung 15.15). Danach können Sie die Stack-Views in der Seitenleiste anklicken und löschen.

392 393

“buch” — 2017/10/6 — 8:49 — page 394 — #390 “buch” — 2017/10/6 — 8:49 — page 395 — #391

15 Hello iOS-World! 15.6 Textgröße mit einem Slider einstellen

Steuerelementen müssen Sie die Größe selbst einstellen – und das erfordert zwei weitere Stack-Views richtig einsetzen Regeln. Stack-Views sind ein durchaus nützliches Feature, das dabei hilft, allzu komplizierte Layout- Sie können vorhandene Regeln nicht ohne Weiteres ändern. Die Dialoge Add New Align- regeln zu vermeiden. Den richtigen Umgang mit Stack-Views erläutere ich Ihnen in ment Constraints bzw. Add New Constraints ersetzen bzw. verändern nicht vorhan- Abschnitt 16.7. dene Regeln, sondern definieren zusätzliche Regeln. Das führt oft zu Regeln, die sich widersprechen. Einen Überblick über alle Regeln erhalten Sie, wenn Sie die Seitenleiste des Storyboard-Editors einblenden (Editor • Show Document Outline). Dort finden Sie eine Die Document-Outline-Seitenleiste verstehen Liste aller Constraints. Wenn Sie eine der Regeln anklicken, wird die betreffende Regel Die Document-Outline zeigt, wie die Steuerelemente (Views) innerhalb eines View-Control- markiert. lers ineinander verschachtelt sind (siehe Abbildung 15.15), und sie hilft dabei, das gewünschte Bei kleinen Projekten ist es bei Problemen oft am einfachsten, alle Regeln zu löschen und Element auszuwählen, wenn zwei Elemente übereinander platziert sind. Innerhalb des noch einmal von vorne zu beginnen. Dazu klicken Sie auf den Button Resolve Auto Lay- Objektbaums erhält jedes Element standardmäßig einen Namen, der seiner Klasse entspricht out Issues und führen All Views in View Controller • Clear Constraints aus. –z.B.View für ein UIView-Objekt. Bei einigen Steuerelementtypen, z. B. bei Buttons und Labels, In Xcode 9 hat es einige Änderungen bei den Layoutregeln gegeben. Beispielsweise zeigt wird der dort eingetragene Text angezeigt – also Noch ein Button statt einfach Button. Xcoden nun eine Warnung an, wenn Sie die Breite von Steuerelementen mit Text fixieren Sie können im Objektbaum alle Objekte durch einfaches Anklicken umbenennen. Das ist dann oder wenn Sie bei einem Button oder Label nur den linken Rand, nicht aber den rechten sinnvoll, wenn es mehrere gleichartige Objekte gibt, die Sie im Storyboard-Editor leichter einstellen. identifizieren wollen. Beachten Sie aber, dass die Objektnamen in der Document-Outline- In beiden Punkten war Xcode 8 toleranter. Xcode 9 zwingt hier zu neuen Arbeitstechni- Seitenleiste ausschließlich für den Storyboard-Editor von Xcode gelten! 15 ken, z. B. zur vermehrten Verwendung der Stack-View oder zur beidseitigen Fixierung der Im Code Ihrer View-Controller-Klasse haben Sie keine Möglichkeit, den Namen festzustellen, horizontalen Ränder. Anfänglich ist das lästig, längerfristig sollten die geänderten Vor- den Sie einem Objekt in der Outline-Seitenleiste gegeben haben. Sie können zur Identifizie- gehensweisen aber robuster sein und vermeiden, dass die Änderung der Beschriftung rung von Steuerelementen im Code auf die tag-Eigenschaft zurückgreifen. In dieser auch in womöglich zu abgeschnittenen Texten führt. Xcode zugänglichen Eigenschaft können Sie allerdings nur eine ganze Zahl speichern. Eine zweite Möglichkeit besteht darin, eine eigene Klasse mit einer neuen Eigenschaft zu definie- ren. Ein Beispiel dafür finden Sie in Abschnitt 20.3, »Focus Engine«. 15.6 Textgröße mit einem Slider einstellen

Als letzte Erweiterung für das Programm fügen wir diesem nun neben dem Button noch Wenn es Probleme gibt einen Slider hinzu, mit dem die Schriftgröße des Textfelds verändert werden kann (siehe Der Umgang mit Layoutregeln ist schwierig und führt häufig dazu, dass sich Xcode über feh- Abbildung 15.16). lende oder über zueinander im Konflikt stehende Regeln beklagt. In Abschnitt 16.5, »Auto Layout«, folgt eine Menge weiterer Details zu diesem Thema. Bis dahin vertröste ich Sie hier Das Slider-Steuerelement hinzufügen mit einigen Tipps: Sie finden das Steuerelement in der Xcode-Objektbibliothek unter dem Namen Slider.Fügen Sobald Sie eine Regel für ein Steuerelement festlegen, müssen Sie die Größe und Position Sie es in den View-Controller ein, und platzieren Sie es so, dass es am rechten und oberen des Steuerelements vollständig durch Regeln bestimmen. Mit anderen Worten: Solange es Rand einrastet, wobei Sie dieselben Abstände wie bei den anderen Steuerelementen einhal- gar keine Regeln gibt, betrachtet Xcode das Steuerelement als unbestimmt und meckert ten. Mit Add Align Constraints fixieren Sie die Abstände nach oben und nach rechts (die nicht. Sobald Sie aber beginnen, Regeln festzulegen, müssen Sie dies so tun, dass keine Werte sollten jeweils 0 lauten) sowie die Breite des Steuerelements (114 in Abbildung 15.17, Unklarheiten verbleiben. aber Sie können natürlich auch eine andere Breite wählen). Die Werte für die Abstände nach Die Anzahl der erforderlichen Regeln ist nicht bei jedem Steuerelement gleich. Manche rechts und nach unten (174 bzw. 11 in Abbildung 15.17) spielen keine Rolle, weil die entspre- Steuerelemente können ihre optimale Größe aus dem Inhalt selbst ermitteln. Das trifft chenden Regeln nicht aktiviert werden. z. B. bei einem Button zu. Hier reichen also Regeln, die die Position festlegen. Bei anderen

394 395

“buch” — 2017/10/6 — 8:49 — page 396 — #392 “buch” — 2017/10/6 — 8:49 — page 397 — #393

15 Hello iOS-World! 15.6 Textgröße mit einem Slider einstellen

Minimum: 12 Maximum: 30 Current: 16

Den Slider mit einer Methode verbinden Damit sind die Arbeiten an der Oberfläche abgeschlossen, und wir können uns wieder der Programmierung zuwenden: Öffnen Sie den Assistenz-Editor, und verschieben Sie den Slider mit (ctrl) in den Code-Bereich. Die Verbindungsparameter stellen Sie wie folgt ein:

Connection = Action: Wir wollen in einer Methode auf das Verschieben des Sliders rea- gieren. Name: Die Methode muss einen Namen bekommen. Ich habe mich für sliderMove ent- schieden. Abbildung 15.16 Die erweiterte Hello-World-App mit einem Slider zur Einstellung der Textgröße, Type UISlider diesmal im Simulator im Querformat ausgeführt = : In der Methode müssen wir die aktuelle Position des Sliders herausfin- den. Deswegen soll die Instanz des Sliders an die Methode übergeben werden. Event = Va lu e Change d: Die Defaulteinstellung passt hier gut – andere Ereignisse inter- essieren uns nicht. 15 Arguments = Sender: Damit wird die Instanz des Sliders als Parameter an die Methode übergeben. Den Datentyp des Parameters haben wir ja bereits mit UISlider festgelegt.

Zu Testzwecken bauen wir in die Methode vorerst nur die print-Funktion ein, um eine Verän- derung des Sliders in Xcode verfolgen zu können. Uns interessiert die value-Eigenschaft, die die Slider-Position im eingestellten Wertebereich als Fließkommazahl liefert:

// wird bei jeder Slider -Bewegung ausgeführt @IBAction func sliderMove(_ sender: UISlider) { // Testausgabe im Debug-Fenster print(sender.value) }

Jetzt geht es nur noch darum, die Schrift des Textfelds entsprechend zu verändern. Dazu lesen wir mit textView.font? die aktuelle Font-Instanz aus, bilden daraus mit der Methode withSize eine neue Instanz in der gewünschten Größe und weisen diese der font-Eigenschaft des Textfelds wieder zu. Da fontWithSize einen CGFloat-Parameter erwartet, muss die Fließ- kommazahl von sender.value in den CGFloat-Typ umgewandelt werden. CGFloat ist auf 32-Bit-Architekturen ein Float, auf 64-Bit-Architekturen aber ein Double. Abbildung 15.17 Layoutregeln für den Slider einstellen // Schriftgröße im Textfeld einstellen @IBAction func sliderMove(_ sender: UISlider) { Mit dem Slider soll die Textgröße in einem Bereich zwischen 12 und 30 Punkt verändert textView.font = textView.font?.withSize(CGFloat(sender.value)) werden. Dazu wählen Sie den Slider aus und stellen im Attributinspektor die folgenden Eigen- } schaften ein:

396 397

“buch” — 2017/10/6 — 8:49 — page 398 — #394 “buch” — 2017/10/6 — 8:49 — page 399 — #395

15 Hello iOS-World! 15.7 Apps auf dem eigenen iPhone/iPad ausführen

15.7 Apps auf dem eigenen iPhone/iPad ausführen

Den iOS-Simulator in Ehren, aber natürlich wollen Sie Ihre Programme auch auf »richti- ger« Hardware testen. Während dazu früher ein kostenpflichtiger Apple-Developer-Account erforderlich war, ist das Ausführen eigener Apps auf eigenen Geräten mittlerweile kostenlos möglich (Free Provisioning). Dazu verbinden Sie im Dialog Preferences • Accounts Xcode mit Ihrer Apple-ID. Außerdem muss Ihr iOS-Gerät durch ein USB-Kabel mit dem Computer verbunden sein. Nach diesen Vorbereitungsarbeiten können Sie das iOS-Gerät in der Symbol- leiste von Xcode anstelle eines Simulators auswählen. Wenn Sie (Š)+(R) drücken bzw. den Run-Button anklicken, überträgt Xcode die Hello-World- App auf das angeschlossene iPhone oder iPad und startet sie dort. Das gelingt nur, wenn Ihr Smartphone oder Tablet entsperrt ist. Bemerkenswert ist, dass trotz der externen Programm- ausführung die Debugging-Funktionen von Xcode aktiv bleiben. Wenn Sie also z. B. einen Breakpoint setzen, wird die App an dieser Stelle angehalten. Sie können in Xcode den Zustand Abbildung 15.18 Xcode 9 erlaubt (endlich) die App-Entwicklung ohne Kabel. der Variablen ergründen und das Programm dann wieder fortsetzen.

Die App bleibt jetzt auf dem iPhone oder iPad. Sie kann dort losgelöst von Xcode ausgeführt Apple Developer Program werden – dann aber ohne Debugging-Möglichkeiten. Sie können Ihre App wie jede andere Bevor Sie eine App in den App Store hochladen können, müssen Sie Ihre App speziell installierte App problemlos wieder löschen, indem Sie sie zuerst länger anklicken und dann vorbereiten und signieren (siehe Kapitel 31, »App Store und Co.«). Das ist nur mit dem Schlüs- 15 auf das x-Symbol drücken. selsystem des Apple Developer Program möglich. Die Mitgliedschaft hat auch andere Vorteile – etwa den unkomplizierten Zugang zu Beta-Versionen von iOS, macOS und Xcode, den Einschränkungen des Free Provisioning Zugang zu Entwicklerforen etc.: Apple bezeichnet das Verfahren zum Ausführen von Apps auf iOS-Geräten ohne Apple- https://developer.apple.com/programs Developer-Account als Free Provisioning. Dabei gibt es aber Einschränkungen: Der Test Dieses Service-Paket lässt sich Apple mit zurzeit 100 EUR pro Jahr bezahlen. Im Gegensatz zu von einigen Zusatzfunktionen erfordert weiterhin einen kostenpflichtigen Apple-Developer- früher, als es verschiedene Entwicklerprogramme für iOS, macOS und Safari gab, hat Apple Account. Das gilt z. B. für In-App-Käufe, den Datenaustausch mit der iCloud oder die Verwen- diese Programme nun zu einem einzigen verbunden. dung der Apple-Pay-Funktionen.

Eine vorhandene oder eine neue Apple-ID verwenden? App-Ausführung ohne Kabel Bevor Sie sich dem Entwicklerprogramm anschließen, müssen Sie sich überlegen, welche Eine praktische Neuerung von Xcode 9 besteht darin, dass Testgeräte nicht mehr ständig Apple-ID Sie hierfür verwenden. Normalerweise spricht nichts gegen Ihre gewöhnliche Apple- über ein USB-Kabel mit Ihrem Computer verbunden bleiben müssen. Um diesen Kom- ID. Sollten Sie diese ID aber schon im Rahmen von iTunes Connect zum Verkauf von Musik oder munikationsmechanismus zu konfigurieren, muss das Gerät aber weiterhin einmalig per Büchern nutzen, dann benötigen Sie eine zweite Apple-ID für das Entwicklerprogramm. Kabel verbunden werden. Anschließend führen Sie in Xcode Window • Devices and Simu- lators aus, wählen Ihr Gerät und aktivieren die Option Connect via Network (siehe Sie können dem Entwicklerprogramm wahlweise als Einzelperson oder als Team beitreten. Abbildung 15.18). Als Einzelperson benötigen Sie dazu lediglich eine Kreditkarte. Nach Abschluss des Bezahl- prozesses kann es ein paar Minuten dauern, bis Ihr Entwicklerzugang freigeschaltet wird und Sie die entsprechende Welcome-E-Mail erhalten.

398 399

“buch” — 2017/10/6 — 8:49 — page 400 — #396 “buch” — 2017/10/6 — 8:49 — page 401 — #397

15 Hello iOS-World! 15.8 Komponenten und Dateien eines Xcode-Projekts

Nun können Sie in den Xcode-Einstellungen im Dialogblatt Accounts mit Add Apple ID Ihre LaunchScreen.storyboard enthält eine spezielle Ansicht der App, die während des Starts Apple-ID mit Xcode verbinden. Von dort gelangen Sie mit View Details in einen weiteren als eine Art Willkommensdialog angezeigt wird (siehe Abschnitt 31.1, »iOS-Artwork (Icons, Dialog, in dem Sie Schlüssel generieren können (siehe Abbildung 15.19). Vorerst benötigen Launch Screen)«). iOS Development Sie lediglich einen Schlüssel zur iOS-Entwicklung (also den Eintrag ). Assets.xcassets dient als Container für die Bilddateien der App. Dazu zählen neben dem Icon der App auch alle anderen Bitmaps, die Sie irgendwann anzeigen möchten. Die Be- sonderheit von Xcassets-Dateien besteht darin, dass Bitmaps in mehreren Auflösungen gespeichert werden können. Bei der Ausführung verwendet iOS dann automatisch die Datei, die am besten zum Display des iOS-Geräts passt (siehe Abschnitt 16.10, »Image- Views und Xcassets«, und Abschnitt 31.1, »iOS-Artwork (Icons, Launch Screen)«). Info.plist enthält diverse Projekteinstellungen in Form einer sogenannten Property List (Key-Value-Datei). Main.storyboard beschreibt das Aussehen und die Eigenschaften der Ansichten (View- Controller) einer App. ViewController.swift enthält den Controller-Code der ersten Ansicht des Storyboards. Für jede weitere Ansicht im Storyboard müssen Sie in der Regel eine weitere Swift-Datei hinzufügen, die eine von UIViewController abgeleitete Klasse definiert (siehe Kapitel 17, »iOS-Apps mit mehreren Ansichten«). 15

Abbildung 15.19 Verwaltung der Schlüssel des iOS-Entwicklerprogramms in Xcode

Nach diesen Vorbereitungsarbeiten wird jedes Gerät, auf dem Sie via Xcode eigene Apps ausführen, in das Entwicklungsprogramm aufgenommen. Insgesamt dürfen Sie pro Jahr maximal 500 Geräte mit Ihrem Konto verbinden: 100 iPhones, 100 iPods, 100 iPads sowie je 100 Apple-TV- und Apple-Watch-Geräte. Einen Überblick über alle mit Ihrem Konto ver- bundenen iOS-Geräte finden Sie auf der Webseite des Entwicklerprogramms: Abbildung 15.20 Überblick über die Code-Dateien im Projektnavigator von Xcode https://developer.apple.com/account/ios/device

Dateien im Navigator verschieben 15.8 Komponenten und Dateien eines Xcode-Projekts Sie können die Dateien des Projekts im Navigator verschieben und in Gruppen bzw. Ver- zeichnisse gliedern. Es spielt für Xcode keine Rolle, in welchem Verzeichnis die Dateien sich Wenn Sie in Xcode ein neues iOS-Projekt starten, besteht dieses standardmäßig schon aus befinden. Xcode findet in jedem Fall alle zum Kompilieren erforderlichen Dateien. Die Organi- einer Menge Dateien (siehe Abbildung 15.20) – und dabei bleibt es nicht. Dieser Abschnitt gibt sation ist lediglich ein Hilfsmittel für Sie, um einen besseren Überblick zu wahren. Ihnen einen kurzen Überblick darüber, welche Datei welchen Zweck hat. Detaillierte Erläute- Eine Neuerung in Xcode 9 besteht darin, dass die im Navigator angezeigten Gruppen rungen zu vielen Dateien folgen dann in den weiteren Kapiteln. tatsächlich in Form von Verzeichnissen im Dateisystem abgebildet werden. In älteren Xcode- AppDelegate.swift enthält Code zur Verarbeitung von Ereignissen des App-Lebenszyklus Versionen war die Gruppenzuordnung virtuell, was mitunter Verwirrung stiftete. (siehe Abschnitt 16.4, »Phasen einer iOS-App«).

400 401

“buch” — 2017/10/6 — 8:49 — page 402 — #398

15 Hello iOS-World!

Weitere Dateien Bei »richtigen« Apps, die also nicht nur Test- oder Beispielcharakter haben, kommen zu den anfänglich vorhandenen Dateien zumeist viele weitere Dateien hinzu:

Weitere Swift-Code-Dateien verbinden Objekte Ihrer Oberfläche mit eigenen Klassen bzw. bilden die innere Logik Ihres Programms ab, also das Datenmodell gemäß des MVC- Musters (siehe Abschnitt 16.1, »Model-View-Controller (MVC)«). Zusätzliche Lokalisierungsdateien enthalten Zeichenketten für alle Sprachen, in denen die App später ausgeführt werden kann (siehe Abschnitt 31.4, »Mehrsprachige Apps«). Ja nach Zielsetzung der App sind außerdem Text-, XML-, HTML-, Datenbank- sowie Audio- und Video-Dateien erforderlich. Diese Dateien werden zusammen mit der App ausgelie- fert (Bundle-Dateien).

Test- und Produktgruppe Neben der eigentlichen Projektgruppe, deren Name mit dem Projektnamen übereinstimmt, kann ein Projekt bis zu drei weitere Gruppen aufweisen:

projektnameTests und projektnameUITests enthält Code und Einstellungen zum automati- sierten Test Ihres Projekts. Das zugrunde liegende XCTest-Framework hat eine ähnliche Zielsetzung wie Unit Tests in anderen Programmiersprachen. In diesem Buch gehe ich darauf allerdings nicht ein. Products enthält das kompilierte Programm. Bei der iOS-App-Entwicklung werden die hier enthaltenen Dateien aber selten benötigt, weil die Ausführung von Apps durch Xcode auto- matisiert ist und eine Weitergabe von Apps an andere Benutzer nur über den App Store möglich ist.

402

“buch” — 2017/10/6 — 8:49 — page 1193 — #1189

Kapitel 40 Breakout

Breakout ist ein klassisches Spielhallenspiel. Es geht darum, mit einem Ball rechteckige Steine (Bricks) abzuschießen. Es ist Aufgabe des Spielers, den Ball mit einem Schläger (Paddle)indem nach unten offenen Spielfeld zu halten. Die erste Version des Spiels wurde 1976 von Atari 40 produziert, wobei die Spiellogik nicht durch ein Programm, sondern in Hardware realisiert wurde.

Abbildung 40.1 Das Spiel »Breakout«

Breakout hat übrigens schon seit Langem mit Apple zu tun: Steve Jobs, der damals für Atari arbeitete, überließ es Steve Wozniak, einen Prototyp für das Spiel zu bauen, bezahlte ihn dafür aber nur schäbig. Nichtsdestotrotz gründeten die beiden wenig später Apple. https://de.wikipedia.org/wiki/Breakout_(Computerspiel)

1193

“buch” — 2017/10/6 — 8:49 — page 1194 — #1190 “buch” — 2017/10/6 — 8:49 — page 1195 — #1191

40 Breakout 40.2 Initialisierung

Aus Entwicklersicht ist Breakout ein dankbares Beispiel für den Einstieg in die Spieleprogram- Level mit einem zweiten Ball, der zwischen Steinen eingeschlossen ist und erst aktiv wird, mierung (siehe auch Kapitel 28, »SpriteKit«): Die hier präsentierte Version umfasst nur rund wenn er »befreit« wird 250 Zeilen, wenn man den Begleit-Code wegrechnet (CGOperators.swift, GameViewControl- nachrückende Steine (d. h., alle 30 Sekunden kommt oben eine zusätzliche Steinreihe ler.swift etc.). hinzu; noch vorhandene Steine werden nach unten verschoben) zunehmende Ballgeschwindigkeit im Spielverlauf

40.1 Programmaufbau 40.2 Initialisierung Die App wurde aus dem Standard-Template für iOS-SpriteKit-Spiele entwickelt. Die wichtigs- ten Dateien sind: Im View-Controller wird die Spielszene geladen. Die Datei GameScene.sks enthält allerdings GameScene.sks enthält die farbige Hintergrund-Bitmap für die einzige Spielszene. nur den orangen Hintergrund des Spiels. In viewDidLoad wird die Größe der Szene eingestellt. Dabei wird die Größe des jeweiligen iOS-Geräts aus dem SKView-Objekt übernommen. GameScene.swift enthält den Großteil des Codes. 40 GameViewController.swift lädt und skaliert die GameScene-Datei. Die eigentliche Initialisierung des Spiels erfolgt durch den Aufruf von setup in der Methode CGOperators.swift enthält Methoden und Operatoren zum eleganteren Umgang mit viewDidAppear. Vielleicht fragen Sie sich, warum die Initialisierung nicht wie sonst üblich CGXxx-Strukturen (siehe Abschnitt 7.3, »CGFloat, CGPoint, CGSize und Co.«). bereits in viewDidLoad erfolgt. Das hat mit den Eigenheiten des iPhone X zu tun: Beim Ein- richten des Spiels muss der oberste Display-Bereich unbenutzt bleiben. Wie viel Platz zur Das Spiel kann nur im Vollbildmodus auf iPhones im Portrait-Modus gespielt werden. Andere Verfügung steht, kann aber erst mit dem Aufruf von viewDidAppear durch die Auswertung Geräteausrichtungen wurden in den Projekteinstellungen deaktiviert. der View-Eigenschaften layoutMargins bzw. safeAreaLayoutGuide ermittelt werden. In Abbildung 40.1 ist Ihnen vielleicht aufgefallen, dass unterhalb des Schlägers relativ viel // Projekt ios-breakout, Datei GameViewController.swift freier Platz ist. Beim Test des Programms hat es sich als praktisch erwiesen, diesen Platz für class GameViewController: UIViewController { die Spielsteuerung frei zu lassen. Das ermöglicht die Steuerung des Schlägers mit einem Fin- ger, ohne dass der Finger den Schläger verdeckt. // Szene aus GameScene.sks laden (oranger Hintergrund) var scene: GameScene! = GameScene(fileNamed: "GameScene")! SpriteKit-Funktionen // die Initialisierung nur einmal durchführen Mit Ausnahme der Hintergrund-Bitmap verwendet die App keine Sprites, sondern nur Sha- var setupDone = false pes (also SKShapeNode-Objekte). Die App nutzt die Physik-Engine: einerseits zur Berechnung der Flugbahn des Balls, andererseits zur Erkennung von Kollisionen mit Steinen. Diese wer- override func viewDidLoad() { den dann aus dem Spielfeld entfernt. Es gibt keine Aktionen (SKAction-Animationen). super.viewDidLoad()

Erweiterungsideen // Initialisierung des Zufallszahlengenerators srand48(Int(arc4random_uniform(100000000))) In dem Spiel gibt es nur einen Level und nur ein Leben. Wenn der Ball aus dem Spielfeld fliegt, wird das Spiel bei der nächsten Berührung des Bildschirms neu gestartet. Wenn Sie Spaß an // Größe der Szene einstellen, Szene anzeigen der App haben, können Sie diverse Erweiterungen programmieren: let skView = self.view as! SKView scene.scaleMode = .aspectFill Counter mit Highscore-Speicherung scene.size = skView.frame.size Verwaltung mehrerer Leben skView.presentScene(scene) Gestaltung weiterer Level, wobei die Steine abwechslungsreicher angeordnet werden kön- } nen (z. B. pyramidenförmig)

1194 1195

“buch” — 2017/10/6 — 8:49 — page 1196 — #1192 “buch” — 2017/10/6 — 8:49 — page 1197 — #1193

40 Breakout 40.2 Initialisierung

// wenn die Game-View zum ersten Mal erscheint, Initialisierung enum GameStatus { // durchführen case waitForStart , running, won, lost override func viewDidAppear(_ animated: Bool) { } super.viewDidAppear(animated) Für die Kollisionserkennung sind am Ende von GameScene.swift außerdem in der Struktur if setupDone { return } scene.setup() PhysCategory einige UInt32-Konstanten definiert: setupDone = true struct PhysCategory { } static let none: UInt32 = 0 } static let ball: UInt32 = 1 static let paddle: UInt32 = 2 Control Center verbergen static let brick: UInt32 = 4 static let frame: UInt32 = 8 Bei allen iOS-Geräten mit Ausnahme des neuen iPhone X können Sie durch Hinaufstreichen } 40 am unteren Bildschirmrand das Control Center öffnen. Ganz lässt sich das nicht verhindern –aberwenndieEigenschaftprefersStatusBarHidden den Zustand true zurückgibt, dann wird Der gesamte weitere Code befindet sich innerhalb der Klasse GameScene. ein versehentliches Öffnen des Control Centers zumindest wesentlich unwahrscheinlicher. Initialisierung der Spielszene override var prefersStatusBarHidden: Bool { return true Die Initialisierung der Spielszene erfolgt in der Methode setup, die in der GameViewController- } Klasse durch viewDidAppear aufgerufen wird. Die sonst übliche Initialisierung in didMove(to:) ist bei dieser App nicht möglich, weil zu diesem Zeitpunkt die Eigenschaften layoutMargins Statusvariablen bzw. safeAreaLayoutGuide noch nicht ausgewertet werden können. Diese Eigenschaften wer- den aber gleich mehrfach benötigt, um die Spielszene so zu gestalten, dass sie auch auf einem GameScene.swift beginnt mit der Deklaration einiger Variablen, die die Eckdaten des Spiels iPhone X korrekt dargestellt wird: bzw. Spielfelds zusammenfassen: Die Höhe des Spielbereichs (Variable h) wird im Vergleich zur Display-Größe um layout- // Projekt ios-breakout, Datei GameScene.swift Margins.top reduziert, also um den Bereich des iPhone-X-Displays, der abgerundet ist. (Bei class GameScene: SKScene { anderen iPhone-Modellen enthält layoutMargins.top den Wert 0. Das Spiel nutzt dann das // Objekte var paddle: SKShapeNode! gesamte Display.) var ball: SKShapeNode! Der Bereich, in dem sich der Ball frei bewegen kann, wird durch ein SKPhysicsBody- var label = SKLabelNode(fontNamed: "AvenirNext-Bold") Objekt eingegrenzt, das genau der Größe der sogenannten Safe Area entspricht (siehe Abbildung 40.2). var w: CGFloat = 0 // enthält Breite und Höhe des SKScene- var h: CGFloat = 0 // Objekts, wird in setup() eingestellt Damit für die Spieler klar ist, wo der Ball oben reflektiert wird, wird der obere Display- Bereich durch ein schwarzes SKShapeNode-Objekt dargestellt. In Abbildung 40.2 ist dieses // Spielstatus Objekt »wall« in grauer Farbe dargestellt. Bei anderen iPhone-Modellen entfällt dieses var brickcounter = 0 Objekt, weil layoutMargins.top dann den Wert 0 zurückgibt. var status = GameStatus.waitForStart } // Projekt ios-breakout, Datei GameScene.swift func setup() { Der aktuelle Spielstatus wird in status gespeichert. Diese Variable kann die Werte der folgen- w = self.frame.width den Enumeration annehmen: h = self.frame.height - self.view!.layoutMargins.top

1196 1197

“buch” — 2017/10/6 — 8:49 — page 1198 — #1194 “buch” — 2017/10/6 — 8:49 — page 1199 — #1195

40 Breakout 40.2 Initialisierung

// keine Gravitation self.physicsWorld.gravity = CGVector.zero

// zur Erkennung, wann ein Ball einen Stein trifft self.physicsWorld.contactDelegate = self

// Spielobjekte zusammenstellen setupBricks(rows: 6, cols: 6) setupPaddle() setupBall() setupText()

// Ball einsperren let gameArea = self.view!.safeAreaLayoutGuide.layoutFrame 40 self.physicsBody = SKPhysicsBody(edgeLoopFrom: gameArea) with(self.physicsBody!) { $0.categoryBitMask = PhysCategory.frame $0.collisionBitMask = PhysCategory.ball $0.contactTestBitMask = PhysCategory.none }

// optische Abgrenzung nach oben (für iPhone X) let wallrect = CGRect(x: 0, y: h, width: w, height: self.view!.layoutMargins.top) let wall = SKShapeNode(rect: wallrect) wall.fillColor = .black Abbildung 40.2 Breakout auf einem iPhone X wall.strokeColor = .black wall.zPosition = 2 Spielsteine einrichten self.addChild(wall) } setupBricks richtet rows Zeilen mit jeweils cols Steinen ein. In brickcounter wird die Gesamt- anzahl der Steine gespeichert. Die Variable hilft später dabei, das Spielende zu erkennen. Die Um bei der Einstellung der Eigenschaften des physikalischen Körpers die wiederholte Nen- Steine werden je nach Zeile in unterschiedlichen Rottönen eingefärbt. Außerdem wird jeder nung von brick.physicsBody! zu vermeiden, habe ich die with-Funktion verwendet, die Stein durch name = "brick" benannt. Das ermöglicht es später, alle Steine unkompliziert aus schon in Abschnitt 28.7, »Kollisionserkennung«, vorgestellt wurde. Sie ist am Ende von der Spielszene zu löschen. GameScene.swift deklariert: isDynamic = false schließt aus, dass sich die Steine bewegen. Die weiteren physicsBody-Eigen- func with(_ object: T, closure: (T)->()) { closure(object) schaften bewirken, dass der Ball von den Steinen abprallt und dass die contactDelegate- } Methode didBegin bei jeder Kollision aufgerufen wird. func setupBricks(rows: Int, cols: Int) { let brickw = w / CGFloat(cols+1) let brickh = brickw / 3 brickcounter = rows * cols

1198 1199

“buch” — 2017/10/6 — 8:49 — page 1200 — #1196 “buch” — 2017/10/6 — 8:49 — page 1201 — #1197

40 Breakout 40.2 Initialisierung

for row in 1...rows { Schläger einrichten (Paddle) let brickColor = Der Schläger ist einfach ein weiteres SKShapeNode-Objekt, das im untersten Bildschirmviertel SKColor.init(red: 0.7 + 0.3 * CGFloat(rows-row) / CGFloat(rows), platziert wird. Damit der Ball vom Schläger abprallt, ist ein physikalischer Körper erforderlich. green: 0.2, blue: 0, Gleichzeitig soll der Schläger aber nicht durch die Regeln der Physik bewegt werden, sondern alpha: 1) ausschließlich durch den Finger auf dem Display. Daher ist isDynamic = false erforderlich. for col in 1...cols { Die BitMask-Einstellungen stellen sicher, dass der Ball vom Schläger abprallt, dass SpriteKit let brick = SKShapeNode(rectOf: aber keine weiteren (rechenaufwendigen) Kollisionsdetektoren aktiviert. CGSize(width: brickw * 0.95, height: brickh * 0.7)) brick.fillColor = brickColor func setupPaddle() { brick.strokeColor = brickColor // Paddle unten positionieren , // Breite ist 1/5 der Bildschirmbreite let x = brickw * CGFloat(col) paddle = SKShapeNode( let y = h - brickh * CGFloat(row+1) brick.position = CGPoint(x: x, y: y) rectOf: CGSize(width: w * 0.20, height: w * 0.04)) 40 brick.zPosition = 10 paddle.fillColor = SKColor.red brick.name = "brick" paddle.strokeColor = SKColor.red self.addChild(brick) paddle.position = brick.physicsBody = SKPhysicsBody(rectangleOf: brick.frame.size) CGPoint(x: w * 0.5, // mittig with(brick.physicsBody!) { y: h * 0.2) // unteres Viertel $0.isDynamic = false paddle.zPosition = 10 $0.categoryBitMask = PhysCategory.brick self.addChild(paddle) $0.contactTestBitMask = PhysCategory.ball $0.collisionBitMask = PhysCategory.ball paddle.physicsBody = SKPhysicsBody(rectangleOf: paddle.frame.size) } with(paddle.physicsBody!) { } // Ende for col $0.isDynamic = false } // Ende for row $0.categoryBitMask = PhysCategory.paddle } // Ende func $0.collisionBitMask = PhysCategory.ball $0.contactTestBitMask = PhysCategory.none } Geschwindigkeitsüberlegungen } Die Anzahl der Spielsteine hat bei diesem Spiel einen großen Einfluss auf den Rechenauf- wand. Bei jedem Frame muss SpriteKit für jeden Spielstein überprüfen, ob dieser mit dem Ball Ball einrichten kollidiert. Das verursacht trotz der einfachen Objektformen einen verblüffend hohen CPU- Der Ball ist ein kreisförmiges SKShapeNode-Objekt. Er wird vertikal etwas oberhalb des Schlä- Aufwand. gers positioniert. Die horizontale Position ist vom Zufall abhängig.

Ich habe das Spiel auf einem iPhone 5S mit 16 ¢ 16 Steinen getestet. Dabei sank die Frame- Den physikalischen Körper wollte ich ursprünglich rund einrichten (also mit SKPhysicsBody Rate auf ca. 20. Sie wurde auch nicht höher, als ich den Ball ins Aus laufen ließ, sich also (circleOfRadius ...)), das hat sich aber nicht bewährt. Es kommt dann recht oft vor, dass sämtliche Objekte im Ruhezustand befanden. SpriteKit ist hier offensichtlich schlecht opti- der Ball auf die Ecke eines Steins trifft und in einem sehr flachen Winkel abprallt. Das mag miert. physikalisch korrekt sein, der Effekt ist aber unvorhersehbar und dem Spiel nicht dienlich. Wenn Sie also eine Profiversion von Breakout programmieren möchten, sollten Sie auf die Ver- Deswegen habe ich den physikalischen Körper einfach quadratisch gewählt. wendung der Physik-Engine verzichten und die Kollisionsberechnungen selbst durchführen. Bei der Einstellung der physikalischen Eigenschaften ist es wichtig, jede Form der Reibung Das ist nicht besonders schwierig und lässt sich für die simple Spielidee sicherlich effizienter oder Dämpfung zu deaktivieren – sonst wird der Ball immer langsamer. Der Ball soll von gestalten, als dies in SpriteKit der Fall ist. allen anderen Körpern abprallen. Eine Kollisionsbenachrichtigung ist aber nur beim Zusam- mentreffen mit einem Stein erforderlich.

1200 1201

“buch” — 2017/10/6 — 8:49 — page 1202 — #1198 “buch” — 2017/10/6 — 8:49 — page 1203 — #1199

40 Breakout 40.3 Spielsteuerung

func setupBall() { // neues Spiel starten: zuerst aufräumen ... ball = SKShapeNode(circleOfRadius: w/35) ball.removeFromParent() ball.fillColor = SKColor.black for ch in self.children { ball.strokeColor = SKColor.black if let childname = ch.name, childname == "brick" { ball.position = CGPoint(x: w * 0.25 + w * 0.5 * cRnd(), y: h*0.3) ch.removeFromParent() ball.zPosition = 10 } self.addChild(ball) } // ... dann das Spielfeld neu einrichten ball.physicsBody = SKPhysicsBody(rectangleOf: ball.frame.size) setupBall() with(ball.physicsBody!) { setupBricks(rows:6, cols:6) $0.friction = 0 ball.physicsBody!.applyImpulse(initialImpulse()) $0.angularDamping = 0 status = .running $0.linearDamping = 0 label.text = "" $0.restitution = 1 self.isPaused = false 40 $0.allowsRotation = false } $0.categoryBitMask = PhysCategory.ball } $0.collisionBitMask = PhysCategory.brick + PhysCategory.frame + // Startimpuls für den Ball PhysCategory.paddle func initialImpulse() -> CGVector { $0.contactTestBitMask = PhysCategory.brick return CGVector(dx: w * 0.05, dy: w * 0.05) } } }

Der Ball ist anfänglich in Ruhe – er wird erst durch die Berührung des Displays in den touches- Schläger steuern Methoden in Bewegung gesetzt. Um die Steuerung des Schlägers kümmert sich die touchesMoved-Methode. Relevant ist dabei nur die X-Koordinate des Berührungspunkts. Sie legt die Position des Schlägermittelpunktes fest. Die in GCOperators.swift definierte minMax-Funktion stellt dabei sicher, dass der Schläger 40.3 Spielsteuerung nicht über den Bildschirmrand bewegt wird.

Die touchesBegan-Methode ist für den Start des Spiels verantwortlich. Beim ersten Spiel mit override func touchesMoved(_ touches: Set, status == .waitForStart ist das Spielfeld bereits eingerichtet. Daher reicht es aus, den Ball with event: UIEvent?) mit applyImpulse in Bewegung zu setzen. Wenn dagegen vorher schon eine Runde gespielt { wurde, müssen der Ball und die Spielsteine neu eingerichtet werden. if touches.count != 1 { return } let touch = touches.first! override func touchesBegan(_ touches: Set, let xnew = touch.location(in: self).x with event: UIEvent?) let xmin = paddle.frame.size.width/2 { let xmax = self.frame.size.width - xmin if status == .waitForStart { paddle.position = CGPoint(x: minMax(xnew, minimum: xmin, maximum: xmax), // erstes Spiel: Ball in Bewegung setzen y: paddle.position.y) ball.physicsBody!.applyImpulse(initialImpulse()) } status = .running label.text = "" touchesEnded und touchesCancelled sind gemäß den Dokumentationsvorgaben ebenfalls } else if status == .won || status == .lost { implementiert, enthalten aber keinen Code. Auf den Abdruck habe ich daher verzichtet.

1202 1203

“buch” — 2017/10/6 — 8:49 — page 1204 — #1200 “buch” — 2017/10/6 — 8:49 — page 1205 — #1201

40 Breakout 40.3 Spielsteuerung

Test, ob der Ball im Aus ist extension GameScene : SKPhysicsContactDelegate { func didBegin(_ contact: SKPhysicsContact) { In der update-Methode wird getestet, ob die Y-Koordinate des Balls kleiner ist als die des Schlä- var brick:SKNode! gers. In diesem Fall ist der Ball im Aus, das Spiel ist verloren und wird pausiert. if contact.bodyA.categoryBitMask == PhysCategory.brick { Ein wenig merkwürdig ist der restliche Code: Während der Tests ist es immer wieder vorge- brick = contact.bodyA.node kommen (circa einmal pro Spiel), dass der Ball von seiner üblichen diagonalen Flugbahn } else if contact.bodyB.categoryBitMask == PhysCategory.brick { abwich und sich gänzlich horizontal bzw. vertikal bewegte. Ein vernünftiges Spiel ist dann brick = contact.bodyB.node } else { nicht mehr möglich. Wenn das passiert, die X- oder Y-Komponente der Geschwindigkeit also return nahe 0 ist, wird die Geschwindigkeit ganz auf 0 zurückgesetzt. Anschließend erhält der Ball } wieder seinen Startimpuls. Diese Maßnahme klingt recht radikal, ist aber im Spielverlauf optisch nicht wahrnehmbar. // Stein entfernen brick.removeFromParent() override func update(_ currentTime: TimeInterval) { 40 if status != .running { return } // Spielende? brickcounter -= 1 // Test, ob das Spiel verloren ist if brickcounter == 0 { if ball.position.y < paddle.frame.minPoint().y { label.text = "Congratulations!" label.text = "Game Over" self.isPaused = true self.isPaused = true status = .won status = .lost } return } } } // manchmal passiert es, dass der Ball sich nur noch horizontal oder // vertikal bewegt; dann muss man der Physik ein wenig nachhelfen if abs(ball.physicsBody!.velocity.dx) <= 0.01 || abs(ball.physicsBody!.velocity.dy) <= 0.01 { ball.physicsBody!.velocity = CGVector.zero ball.physicsBody!.applyImpulse(initialImpulse()) } }

Kollisionserkennung

Wenn der Ball einen Stein trifft, wird die Methode didBegin des SKPhysicsContactDelegate- Protokolls aufgerufen. In der Methode verweist dann contact.bodyA oder contact.BodyB auf diesen Stein. Er wird einfach entfernt. (Wenn Sie möchten, können Sie hier eine nette Anima- tion einbauen, die den Stein explodieren oder in sich zusammenfallen lässt.) Sollte die Anzahl der Steine damit auf 0 sinken, hat der Spieler bzw. die Spielerin das Spiel gewonnen.

1204 1205

Auf einen Blick

Auf einen Blick

Teil I Swift ...... 19

Teil II App-Programmierung ...... 371

Teil III Programmier- und Arbeitstechniken ...... 575

Teil IV Beispielprojekte ...... 1041

“buch” — 2017/10/6 — 8:49 — page 5 — #1

Inhalt

Vorwort ...... 15

TEIL I Swift

1 Hello World! ...... 21

1.1 »Hello World« im Playground ...... 21 1.2 »Hello World« als Terminal-App ...... 31 1.3 »Hello World« auf dem iPad ...... 39

2Swift-Crashkurs...... 41

2.1 Elementare Syntaxregeln und Kommentare ...... 41 2.2 Variablen, Konstanten und Datentypen ...... 46 2.3 Strukturierung des Codes ...... 50 2.4 Klassen und Datenstrukturen ...... 54 2.5 Fehlerabsicherung ...... 56 2.6 Xcode-Crashkurs ...... 58

3Operatoren...... 71

3.1 Zuweisungs- und Rechenoperatoren ...... 71 3.2 Vergleichsoperatoren und logische Operatoren ...... 76 3.3 Range-Operatoren ...... 80 3.4 Operatoren für Fortgeschrittene ...... 84 3.5 Eigene Operatoren ...... 87

4 Variablen und Optionals ...... 93

4.1 Variablen und Konstanten ...... 93 4.2 Optionals ...... 99 4.3 Wert- versus Referenztypen ...... 104

5

“buch” — 2017/10/6 — 8:49 — page 6 — #2 “buch” — 2017/10/6 — 8:49 — page 7 — #3

Inhalt Inhalt

5 Verzweigungen und Schleifen ...... 107 10.3 Dictionaries ...... 226 10.4 Sets ...... 230 5.1 Verzweigungen mit if ...... 107 10.5 Option-Sets ...... 231 5.2 Inverse Logik mit guard ...... 110 10.6 Tupel ...... 233 5.3 Verzweigungen mit switch ...... 112 10.7 Lottosimulator ...... 235 5.4 Versions- oder plattformabhängiger Code ...... 115 5.5 Schleifen ...... 117 11 Objektorientierte Programmierung I ...... 241 5.6 Nicht triviale Schleifen ...... 121 11.1 Klassen und Strukturen ...... 242 6 Funktionen und Closures ...... 127 11.2 Enumerationen ...... 250 11.3 Eigenschaften ...... 254 6.1 Funktionen definieren und ausführen ...... 127 11.4 Init- und Deinit-Funktion ...... 266 6.2 Parameter ...... 138 11.5 Methoden ...... 271 6.3 Standardfunktionen ...... 145 11.6 Subscripts ...... 278 6.4 Funktionale Programmierung ...... 149 11.7 Typ-Aliasse ...... 281 6.5 Closures ...... 154 11.8 Speicherverwaltung ...... 282

7 Zahlen und geometrische Strukturen ...... 165 12 Objektorientierte Programmierung II ...... 287 7.1 Zahlen und boolesche Werte ...... 165 12.1 Vererbung ...... 287 7.2 NSNumber ...... 170 12.2 Generics ...... 299 7.3 CGFloat, CGPoint, CGSize und Co...... 171 12.3 Protokolle ...... 304 12.4 Standardprotokolle ...... 314 8 Zeichenketten ...... 179 12.5 Extensions ...... 322 8.1 Syntax ...... 180 12.6 Protokollerweiterungen ...... 328 8.2 Bearbeitung von Zeichenketten ...... 184 12.7 Reflection und Metatypen ...... 331 8.3 Suchen und ersetzen ...... 188 8.4 Zeichenketten zerlegen und zusammensetzen ...... 191 13 Fehlerabsicherung ...... 337

8.5 Zeichenketten und Zahlen umwandeln ...... 197 13.1 Fehlerabsicherung mit try und catch ...... 337 8.6 Zeichenketten und binäre Daten umwandeln (Data-Struktur) ...... 201 13.2 Selbst Fehler auslösen (throws und throw) ...... 346 13.3 Fehler in Funktionen weitergeben (rethrows) ...... 350 9 Datum und Uhrzeit ...... 203 13.4 Das Error-Protokoll ...... 354 9.1 Datum und Uhrzeit ermitteln und darstellen ...... 203 13.5 Fehlerabsicherung von API-Methoden (NSError) ...... 355 9.2 Rechnen mit Datum und Uhrzeit ...... 205 14 Importe, Attribute und Systemfunktionen ...... 359 10 Arrays, Dictionaries, Sets und Tupel ...... 207 14.1 Module, Frameworks und Importe ...... 359 10.1 Arrays ...... 207 14.2 Attribute ...... 363 10.2 Arrays und Aufzählungen verarbeiten ...... 217 14.3 Systemfunktionen aufrufen ...... 365

6 7

“buch” — 2017/10/6 — 8:49 — page 8 — #4 “buch” — 2017/10/6 — 8:49 — page 9 — #5

Inhalt Inhalt

TEIL II App-Programmierung 18 Hello macOS-World! ...... 507

18.1 Von iOS zu macOS ...... 507 15 Hello iOS-World! ...... 373 18.2 Lottozahlengenerator ...... 509

15.1 Projektstart ...... 374 19 macOS-Grundlagen ...... 519 15.2 Gestaltung der App ...... 375 15.3 Steuerung der App durch Code ...... 380 19.1 Programme mit mehreren Fenstern ...... 519 15.4 Actions und Outlets für Fortgeschrittene ...... 385 19.2 Tab-View-Controller ...... 526 15.5 Layout optimieren ...... 388 19.3 Standarddialoge ...... 533 15.6 Textgröße mit einem Slider einstellen ...... 395 19.4 Tastatur ...... 538 15.7 Apps auf dem eigenen iPhone/iPad ausführen ...... 398 19.5 Menüs ...... 543 15.8 Komponenten und Dateien eines Xcode-Projekts ...... 400 19.6 Programme ohne Menü ...... 552

16 iOS-Grundlagen ...... 403 20 tvOS ...... 555

16.1 Model-View-Controller (MVC) ...... 403 20.1 Hello tvOS! ...... 556 16.2 Klassenhierarchie einer App-Ansicht ...... 407 20.2 Fernbedienung auswerten ...... 561 20.3 Focus Engine ...... 567 16.3 Die UIViewController-Klasse ...... 410 16.4 Phasen einer iOS-App ...... 414 16.5 Auto Layout ...... 417 TEIL III Programmier-und Arbeitstechniken 16.6 Layoutregeln durch Code definieren ...... 433 16.7 Steuerelemente in einer Stack-View anordnen ...... 435 21 Dateien und User-Defaults ...... 577 16.8 Layoutvarianten ...... 440 16.9 Texteingaben ...... 448 21.1 User-Defaults ...... 577 16.10 Image-Views und Xcassets ...... 455 21.2 Dateinamen und URLs ...... 582 21.3 Bundle-Dateien und Assets ...... 584 17 iOS-Apps mit mehreren Ansichten ...... 459 21.4 Standardverzeichnisse ...... 586 21.5 Dateioperationen ...... 590 17.1 Storyboard und Controller-Klassen verbinden ...... 459 21.6 Wie geht’s weiter? ...... 599 17.2 Ansichten durch Segues verbinden ...... 460 17.3 Segues mit Datenübertragung ...... 465 22 Netzwerk, XML und JSON ...... 601 17.4 Navigation-Controller ...... 470 17.5 Tab-Bar-Controller ...... 476 22.1 Dateien per HTTP/HTTPS laden ...... 601 17.6 Split-View-Controller ...... 482 22.2 XML-Dokumente auswerten ...... 610 17.7 Popups ...... 493 22.3 JSON-Encoder und -Decoder ...... 614 17.8 Ja/Nein-Dialoge (UIAlertController) ...... 503 22.4 Webseiten anzeigen ...... 621

8 9

“buch” — 2017/10/6 — 8:49 — page 10 — #6 “buch” — 2017/10/6 — 8:49 — page 11 — #7

Inhalt Inhalt

23 Tabellen und Listen darstellen ...... 629 27.8 Fotos mit der Picker-View auswählen und aufnehmen ...... 788 27.9 Fotos in einer AVCaptureSession aufnehmen ...... 791 23.1 Listen in iOS-Apps (UITableView) ...... 629 27.10 Barcodes in einer AVCaptureSession erkennen ...... 799 23.2 Prototypzellen ...... 635 23.3 Individuelle Gestaltung von Listenzellen ...... 640 28 SpriteKit ...... 803 23.4 Veränderliche Listen ...... 647 23.5 Tabellen in macOS-Apps (NSTableView) ...... 650 28.1 Hello SpriteKit! ...... 804 23.6 Collections asynchron füllen (UICollectionView) ...... 661 28.2 Sprites erzeugen und bewegen ...... 813 28.3 Spielsteuerung durch Touch-Ereignisse ...... 819 24 GPS- und Kompassfunktionen ...... 671 28.4 Bewegungssteuerung (Gyroskop und Accelerometer) ...... 825 28.5 Aktionen ...... 832 24.1 Hello MapView! ...... 671 28.6 Der Game-Loop ...... 838 24.2 Wegstrecke aufzeichnen ...... 676 28.7 Kollisionserkennung ...... 840 24.3 Kompassfunktionen ...... 683 28.8 Minispiel: Luftballone abschießen ...... 845 28.9 Physik ...... 852 25 Grafik und Animation ...... 687 28.10 Minispiel: Pyramide zerstören ...... 858 25.1 Eigene Steuerelemente mit Grafikfunktionen ...... 687 28.11 Scene-Editor ...... 865 25.2 Kompass-Steuerelement ...... 694 28.12 Partikel-Emitter ...... 872 25.3 Core Graphics ...... 702 25.4 Animationen ...... 706 29 iCloud ...... 875

29.1 iCloud-Grundlagen ...... 875 26 Touch, Maus, Gestures und Drag & Drop ...... 711 29.2 Key/Value-Speicher ...... 881 26.1 Touch ...... 711 29.3 CloudKit-Grundlagen ...... 888 26.2 Maus ...... 718 29.4 CloudKit-Programmiertechniken ...... 896 26.3 Gestures ...... 725 29.5 CloudKit-Beispiel ...... 906 26.4 Drag & Drop (macOS) ...... 728 26.5 Drag & Drop (iOS) ...... 742 30 Asynchrone Programmierung ...... 919

27 Audio, Video und Fotos ...... 757 30.1 Hello Grand Central Dispatch! ...... 920 30.2 GCD-Grundlagen ...... 923 27.1 Audio-Wiedergabe mit dem AVAudioPlayer ...... 757 30.3 Parallel rechnen ...... 928 27.2 Audio-Wiedergabe mit dem AVPlayer ...... 768 30.4 Die Async-Bibliothek ...... 935 27.3 Audio-Wiedergabe mit dem AVPlayerViewController ...... 770 27.4 Audio-Aufnahmen mit dem AVAudioRecorder durchführen ...... 772 31 App Store und Co...... 937 27.5 Videos abspielen ...... 777 27.6 Videos mit der Picker-View auswählen und aufnehmen ...... 781 31.1 iOS-Artwork (Icons, Launch Screen) ...... 938 27.7 YouTube-Videos abspielen ...... 785 31.2 macOS-Artwork (Icon) ...... 940 31.3 tvOS-Artwork (Parallax-Icons, Launch und Top Shelf Image) ...... 941

10 11

“buch” — 2017/10/6 — 8:49 — page 12 — #8 “buch” — 2017/10/6 — 8:49 — page 13 — #9

Inhalt Inhalt

31.4 Mehrsprachige Apps ...... 947 35.4 Popup-View-Controller-Klasse ...... 1069 31.5 Eigene Apps im App Store anbieten ...... 956 35.5 iCloud-Variante ...... 1070 31.6 macOS-Programme selbst weitergeben ...... 964 36 Schatzsuche ...... 1075 32 Xcode-Arbeitstechniken ...... 971 36.1 Aufbau der App ...... 1075 32.1 Simulator-Ausgaben stoppen ...... 971 36.2 Datenmodell ...... 1080 32.2 Header-Code einer eigenen Klasse erzeugen ...... 972 36.3 Location Manager selbst gemacht ...... 1082 32.3 Versionsverwaltung mit Git ...... 973 36.4 Steuerelement zur Richtungsanzeige (UIBezierPath) ...... 1086 32.4 Crashlogs ...... 976 36.5 Hauptansicht mit Listenfeld ...... 1087 32.5 Refactoring ...... 977 36.6 Popup-Dialog zum Speichern ...... 1092 32.6 Projekte umbenennen ...... 978 36.7 Detailansicht mit Richtungspfeil ...... 1093 32.7 Xcode-Verzeichnisse aufräumen ...... 979 32.8 Apple Configurator ...... 982 37 Währungskalkulator ...... 1101

37.1 App-Überblick ...... 1101 33 Server-side Swift ...... 985 37.2 Kurse ermitteln ...... 1107 33.1 Swift unter Linux ...... 988 37.3 Das Datenmodell der App ...... 1110 33.2 kennenlernen ...... 995 37.4 Umrechnungsansicht ...... 1113 33.3 Die Vapor-Toolbox ...... 1004 37.5 Einstellungsansicht ...... 1119 33.4 Vapor-Grundlagen ...... 1006 37.6 Internationalisierung und Lokalisierung ...... 1124 33.5 Datenbankanbindung mit Fluent ...... 1017 33.6 Authentifizierung und Autorisierung ...... 1028 38 Fünf Gewinnt ...... 1127 33.7 Deployment ...... 1036 38.1 Die App »Fünf Gewinnt« ...... 1127 38.2 Enumerationen und globale Funktionen (Globals.swift) ...... 1130 TEIL IV Beispielprojekte 38.3 Die Spiellogik (FiveWins.swift) ...... 1134 38.4 Darstellung des Spielbretts und der Steine (BoardView.swift) ...... 1145

34 New-York-Times-Bestseller ...... 1043 38.5 Steuerung des Spielablaufs (ViewController.swift) ...... 1155 38.6 Der Popup-Dialog (PopupVC.swift) ...... 1160 34.1 New-York-Times-API ...... 1045 38.7 Erweiterungsmöglichkeiten ...... 1162 34.2 Benutzeroberfläche ...... 1048

34.3 Split-View-Variante ...... 1053 39 Icon-Resizer ...... 1165

35 To-do-Listen ...... 1059 39.1 App-Überblick ...... 1165 39.2 Icons verwalten (IconSize-Struktur) ...... 1171 35.1 Gestaltung der Benutzeroberfläche ...... 1060 39.3 Hauptfenster (ViewController.swift) ...... 1177 35.2 Datenmodell ...... 1061 39.4 Drag & Drop-Quelle für Icons (IconCellView.swift) ...... 1185 35.3 View-Controller-Klasse ...... 1062 39.5 Drag & Drop-Empfänger für Icons (OriginalIconView.swift) ...... 1186

12 13

“buch” — 2017/10/6 — 8:49 — page 14 — #10

Inhalt

39.6 Popup-Menü (IconChoiceVC.swift) ...... 1189 39.7 Temporäres Verzeichnis erstellen und löschen ...... 1190

40 Breakout ...... 1193

40.1 Programmaufbau ...... 1194 40.2 Initialisierung ...... 1195 40.3 Spielsteuerung ...... 1202

41 Pac-Man selbst gemacht ...... 1207

41.1 Programmaufbau ...... 1208 41.2 Der Tile-Editor »Tiled« ...... 1210 41.3 Globale Konstanten, Datenstrukturen und Enumerationen ...... 1214 41.4 Initialisierung des Spiels ...... 1216 41.5 Die Maze-Klasse ...... 1220 41.6 Aufbau der Spielszene (setup-Methoden) ...... 1224 41.7 Spielsteuerung (touch-Methoden) ...... 1230 41.8 Bewegung des Pac-Mans ...... 1235 41.9 Steuerung der Monster ...... 1239 41.10 Kollisionen ...... 1245 41.11 Apple-TV-Variante von Pac-Man ...... 1249 41.12 Pac-Man-Figuren zeichnen ...... 1252

42 Asteroids ...... 1255

42.1 Programmaufbau ...... 1256 42.2 Globale Konstanten und Funktionen ...... 1258 42.3 Programmstart und Tastaturereignisse (GameViewController) ...... 1258 42.4 Initialisierung des Spiels (GameScene) ...... 1261 42.5 Spielablauf (ebenfalls in GameScene) ...... 1267 42.6 Fokussierbare Menütexte (MyLabel) ...... 1273 42.7 Der Einstellungsdialog (MainScene) ...... 1274

Index ...... 1281

14

“buch” — 2017/10/6 — 8:49 — page 1281 — #1277

Index

_-Zeichen (Wildcard-Pattern) ...... 72 all-Methode (Vapor/Fluent) ...... 1021 &-Zeichen (inout-Parameter) ...... 142 allowsRotation-Eigenschaft ...... 857 alpha-Eigenschaft ...... 708, 1248 815 A SpriteKit ...... alternate-Eigenschaft ...... 720 759 AAC-Format ...... Ambiguous Use of Function (Fehlermeldung) 134 1010 Abort-Struktur (Vapor) ...... anchorPoint-Eigenschaft ...... 814, 1218 ...... 146 abs-Funktion angularDamping-Eigenschaft ...... 857, 1201 Abstand zwischen zwei Koordinaten- angularVelocity-Eigenschaft ...... 857 punkten ...... 1096 animate-Methode ...... 706, 834, 1150 Accelerometer ...... 825 Animationen ...... 706 accelerometerUpdateInterval-Eigenschaft ...... 827 im Spiel 5-Gewinnt ...... 1150 acceptsFirstResponder-Eigenschaft ...... 539 SpriteKit-Aktionen ...... 834, 1227 accountStatus-Methode ...... 896 Any-Datentyp ...... 319 action-Eigenschaft (NSMenuItem) ...... 553 AnyClass-Datentyp ...... 320 action-Parameter AnyObject-Datentyp ...... 319 addTarget ...... 433 Apache-Konfiguration (Vapor) ...... 1038 Gesture Recognizer ...... 1063 API-Design-Richtlinien ...... 141 Actions ...... 380, 405 API-Version testen ...... 115 macOS ...... 515 App SpriteKit ...... 832 ...... 962 umbenennen ...... 386 Archiv erzeugen 398 activateFileViewerSelecting-Methode ...... 1179 auf iOS-Geräten ausführen ...... 565 Activity-Indictator-View ...... 920 beenden ...... 584 adaptivePresentationStyle-Methode ...... 495 Bundle-Dateien ...... 373 add-Methode ...... 167 Hello World ...... 938 1165 addAction-Methode ...... 504 Icon ...... , 958 addButtonWithTitle-Methode ...... 534 ID ...... 962 addConstraint-Methode ...... 434 im App Store einreichen ...... 378 addGestureRecognizer-Methode ...... 728 im Simulator ausprobieren ...... 414 adding-Methode ...... 167 Lebenszyklus ...... 947 addInput-Methode ...... 794 Lokalisierung ...... 940 addInteraction-Methode ...... 745 Name ...... 947 addObserver-Methode ...... 699, 883, 1085 Sprache ...... 577 addOutput-Methode ...... 794 User-Defaults ...... 956 addSublayer-Eigenschaft ...... 778 weitergeben (iOS) ...... addSubview-Methode ...... 433, 1122, 1150, 1182 weitergeben (macOS) ...... 964 addTarget-Methode ...... 433 Willkommensbildschirm ...... 939 Adjust-Scroll-View-Insets-Option ...... 1049 App Store ...... 956 afconvert-Kommando ...... 759 App Transport Security ...... 626, 1053 affectedByGravity-Eigenschaft ...... 857 AppDelegate-Klasse ...... 1190 Aktionen (SpriteKit) ...... 832 Init-Funktion ...... 530 Aktuelles Verzeichnis ermitteln/ändern ...... 588 iOS ...... 415 Alert-Dialog ...... 503 Split-View-Controller-Beispiel ...... 488 alertStyle-Eigenschaft ...... 535 appdmg-Kommando ...... 968 Align-Button ...... 418 append-Methode ...... 213 alignment-Eigenschaft ...... 658 Zeichenketten ...... 192 Stack-View ...... 436 appendArc-Methode ...... 722

1281

“buch” — 2017/10/6 — 8:49 — page 1282 — #1278 “buch” — 2017/10/6 — 8:49 — page 1283 — #1279

Index Index

appendBezierPathWithRoundedRect- associativity-Schlüsselwort ...... 88, 89 AVCaptureDeviceInput-Klasse ...... 791 Binärer Operator ...... 84 Methode ...... 733 Assoziative Arrays ...... 226 AVCaptureMetadataOutputObjectsDelegate- BinaryFloatingPoint-Protokoll ...... 167 799 appendingPathComponent-Methode ...... 583 Assoziativität ...... 86 Protokoll ...... BinaryInteger-Protokoll ...... 313, 324 791 appendingPathExtension-Methode ...... 583 Asteroids-Spiel ...... 1255 AVCapturePhotoCaptureDelegate-Protokoll ..... Bitmap-Literale ...... 811 791 799 Apple Configurator ...... 982 Async-Bibliothek ...... 935 AVCapturePhotoOutput-Klasse ...... , bitmapLiteral-Schlüsselwort ...... 811 791 796 Apple Developer Program ...... 22, 399 async-Methode ...... 609, 922 AVCapturePhotoSettings-Klasse ...... , Bitmaps 791 Apple Movie Trailers ...... 661 CloudKit-Beispiel ...... 912 AVCaptureSession-Klasse ...... als PNG-Datei speichern ...... 1175, 1252 791 Apple TV ...... 555 Trailer-Beispiel ...... 666, 667 AVCaptureVideoPreviewLayer-Klasse ...... Atlas ...... 833, 1209 775 Asteroids-Spiel ...... 1255 asyncAfter-Funktion ...... 925, 1133 AVEncoderAudioQualityKey-Konstante ...... erzeugen (macOS) ...... 1254 775 Pac-Man ...... 1249 Asynchrone Programmierung ...... 919 AVFormatIDKey-Konstante ...... für Sprites ...... 813 758 application-Methode ...... 415 Asynchroner Download ...... 604 AVFoundation-Bibliothek ...... Images.xcassets-Datei ...... 455, 639 768 applicationDidBecomeActive-Methode ...... 415 Atlas (SpriteKit) ...... 833, 1209 AVItem-Klasse ...... NSImage-Klasse ...... 1173 758 applicationDidEnterBackground-Methode ...... 415 Atomic Transaction (CloudKit) ...... 891 AVKit-Bibliothek ...... skalieren ...... 1173 775 639 applicationDidFinishLaunching-Methode ...... 1190 atomically-Parameter ...... 595 AVNumberOfChannelsKey-Konstante ...... UIImage-Klasse ...... 768 75 applicationWillEnterForeground-Methode ...... 415 ATS (App Transport Security) ...... 602 AVPlayer-Klasse ...... Bitweises Rechnen ...... 770 1248 applicationWillResignActive-Methode ...... 415 attitude-Eigenschaft ...... 828 in einem AVPlayerViewController ...... blendMode-Eigenschaft ...... 769 856 applicationWillTerminate-Methode ...... 416, 1190 Attribute ...... 363 AVPlayerItemDidPlayToEndTime-Konstante .... Bodies (SpriteKit) ...... 778 845 applyAngularImpulse-Methode ...... 858 attribute-Methode ...... 610 AVPlayerLayer-Klasse ...... bodyA/bodyB-Eigenschaft ...... 770 170 applyForce-Methode ...... 858 attributesOfFileSystem-Eigenschaft ...... 560 AVPlayerViewController-Klasse ...... Bool-Datentyp ...... 777 170 applyImpulse-Methode ...... 858, 863 attributesOfItem-Methode ...... 591 Video abspielen ...... Boolesche Werte ...... 775 591 applyTorque-Methode ...... 858 Audio ...... 757 AVSampleRateKey-Konstante ...... boolValue-Eigenschaft ...... 413 ARC ...... 282 aufnehmen ...... 772 borderColor-Eigenschaft ...... 413 arch-Test ...... 116 beschleunigt wiedergeben ...... 770 B borderWidth-Eigenschaft ...... 432 Archiv (Xcode) ...... 962 Bibliotheken ...... 758 472 Bottom Layout Guide ...... Back-Button ...... 499 689 719 847 1153 arguments-Eigenschaft ...... 369 759 bounds-Eigenschaft ...... , , , , Datei abspielen ...... Background Capabilities ...... 677, 763 207 759 Box2D-Engine ...... 852 Arrays ...... Formate ...... backgroundColor-Eigenschaft 324 834 break-Schlüsselwort Array-Struktur erweitern ...... SpriteKit-Aktion ...... Collection-View-Zelle ...... 666 226 769 Schleifen ...... 119 assoziative ...... Stream abspielen ...... SpriteKit ...... 1217 211 775 switch ...... 113 auslesen ...... audioRecorderDidFinishRecording-Methode .. UIView ...... 1150 226 768 brew-Kommando ...... 968, 995 Doppelgänger entfernen ...... AudioServicesPlaySystemSound-Funktion ...... Badge-Eigenschaft (Tab-Bar-Item) ...... 479 225 132 Bridging-Header-Datei ...... 366 durchwürfeln ...... Aufräumarbeiten durchführen (defer) ...... Bar-Button-Item ...... 473 220 1029 brighter-Methode ...... 1132 filter, map und reduce ...... Auth- und AuthProvider-Bibliothek (Vapor) ... Barcodes erkennen ...... 799 Bundle-Dateien ...... 584 Fixed Sized Arrays ...... 216 Authentifizierung (Vapor) ...... 1028 1035 bcrypt-Algorithmus ...... 957 210 388 417 Bundle-ID ...... initialisieren ...... Auto Layout ...... , bcrypt.json-Datei (Vapor) ...... 1035 in iTunes Connect ...... 960 mehrdimensionale ...... 216, 1132 deaktivieren ...... 418 1030 Bearer-Token (Vapor) ...... 584 214 417 Bundle-Klasse ...... sortieren ...... Maßeinheit ...... Bechmarktests ...... 205 Buttons verändern ...... 213 Regeln durch Code definieren ...... 433 452 539 1069 becomeFirstResponder-Methode .... , , 377 1132 iOS ...... zweidimensionale ...... Varianten ...... 440 Beispiel ...... 1092 macOS ...... 1168 ArraySlice-Datentyp ...... 212 800 329 Auto-Fokus (Kamera) ...... Bedingte Protokollerweiterungen ...... 1168 1086 Textured Button ...... ArrowView-Klasse (Beispiel) ...... autoclosure-Attribut ...... 157 beginDraggingSession-Methode ...... 730 buttonWithType-Methode ...... 433 as-Operator ...... 78, 297, 298, 331 autoFocusRangeRestriction-Eigenschaft ...... 800 beginRefreshing-Methode ...... 649 Aspect-Fill-Einstellung ...... 431, 457 Automatic Reference Counting ...... 282 Benannte Parameter ...... 128 Aspect-Fit-Einstellung ...... 431, 457 Autoresizing-Option ...... 429 in Protokollen ...... 305 C assert-Funktion ...... 345 available-Attribut ...... 363 Init-Funktion ...... 267 Cache-Verzeichnis ...... 1111 Assets ...... 584 available-Test ...... 115 Benutzernamen feststellen ...... 903 cachesDirectory-Konstante ...... 587 Bitmaps ...... 585 availableFonts-Methode ...... 536 Beschleunigungsmesser ...... 825 CAF-Format ...... 759 CloudKit ...... 878, 891 AVAsset-Klasse ...... 768 Beta-Versionen installieren (iOS, tvOS) ...... 982 CALayer-Klasse ...... 413, 778, 1150 Farben ...... 586 AVAudioPlayer-Klasse ...... 759 Bewegungssteuerung ...... 825 Camera Roll ...... 788 speichern (CloudKit) ...... 898 AVAudioRecorder-Klasse ...... 772 Bibliotheken (Server-side Swift) ...... 992 cameraDevice-Eigenschaft ...... 790 Assets.xcassets-Datei ...... 455 AVAudioRecorderDelegate-Protokoll ...... 775 Bild herunterladen ...... 602 canBecomeFocused-Eigenschaft ...... 568 Associated Values ...... 252 AVAudioSession-Klasse ...... 773 Binäre Datei herunterladen ...... 602 Asteroids-Spiel ...... 1273 Associated Type Constraints ...... 312 AVCaptureDevice-Klasse ...... 791 Binäre Daten ...... 201 in SpriteKit-Apps ...... 572 associatedtype-Schlüsselwort ...... 312 AVCaptureDeviceDiscoverySession-Klasse ...... 795 Binäre Zahlen ...... 166 cancelOperation-Methode ...... 540

1282 1283

“buch” — 2017/10/6 — 8:49 — page 1284 — #1280 “buch” — 2017/10/6 — 8:49 — page 1285 — #1281

Index Index

canCreateDirectories-Eigenschaft ...... 535 CKRecordID-Klasse ...... 899, 903 CompassView-Steuerelement (Beispiel) ...... 694 Core Location (CL) ...... 672 canEditRowAt-Parameter ...... 1067 CKRecordZone-Klasse ...... 891 Compiler ...... 38 CoreAudio-Bibliothek ...... 758 canMoveRowAt-Parameter ...... 1067 CKReference-Klasse ...... 899 completion-Parameter ...... 707, 1161 CoreMotion-Bibliothek ...... 827 Canvas-Value-Einstellung ...... 422 CKUserIdentity-Klasse ...... 903 components-Methode ...... 192, 204 cornerRadius-Eigenschaft ...... 413 Capabilities ...... 677, 763 Class and Subtype Existentials ...... 308 Zeichenketten in Zeilen zerlegen ...... 369 count-Eigenschaft ...... 184, 211, 229 Maps ...... 675 class-Schlüsselwort ...... 244, 275 compositingOperation-Eigenschaft ...... 1253 CountableClosedRange-Struktur ...... 80 capacity-Eigenschaft ...... 215 clipToBounds-Eigenschaft ...... 457 Compound Types ...... 234 CountablePartialRangeFrom-Struktur ...... 80 capitalized-Eigenschaft ...... 186 CLLocation-Klasse ...... 1096 Compression Resistance Priority ...... 438 CountableRange-Struktur ...... 80 Capture List ...... 161 CLLocationManager-Klasse ...... 672, 679 Computed Properties ...... 96, 259 Crashlogs ...... 976 791 799 683 capture-Methode ...... , Kompass ...... Extensions ...... 327 createArray2D-Funktion ...... 1132 1082 Capture-Session teilen ...... Fehler auslösen ...... 349 createDirectoryAtPath-Methode ...... 1191 799 678 683 847 Barcodes erkennen ...... CLLocationManagerDelegate-Protokoll ..... , preferredContentSize ...... 497 cRnd-Funktion ...... 791 525 1035 Fotos aufnehmen ...... close-Methode ...... prefersStatusBarHidden ...... 438 crypto.json-Datei (Vapor) ...... 791 796 80 588 capturePhoto-Methode ...... , Closed-Range-Operator ...... Vererbung ...... 291 currentDirectoryPath-Eigenschaft ...... 159 1086 769 Capturing Values ...... closePath-Methode ...... concludeDragOperation-Methode ...... 730, 741 currentTime-Eigenschaft ...... 361 154 314 1080 Carthage ...... Closures ...... Concurrent Queues ...... 923 CustomStringConvertible-Protokoll ...... , 112 157 case-Schlüsselwort ...... Auto-Closures ...... Config-Klasse (Vapor) ...... 1007 Casting ...... 297, 331 Capture List ...... 161 Connections Inspector ...... 631, 652 D catch-Schlüsselwort ...... 338, 340 Capturing Values ...... 159 constrainMaxCoordinate-Parameter ...... 1181 categoryBitMask-Eigenschaft ...... 843, 857 für Lazy Properties ...... 256 darker-Methode ...... 1132 constrainMinCoordinate-Parameter ...... 1181 cellForRow-Parameter ...... 632 Fehler (rethrows) ...... 350 Dashboard (iCloud) ...... 892 Constraints (Auto Layout) ...... 388, 417 CG-Kürzel ...... 702 in Animationen ...... 706 data-Methode ...... 201 contactBitMask-Eigenschaft ...... 843 CGColor-Klasse ...... 413 throws/rethrows ...... 351 String ...... 617 contactTestBitMask-Eigenschaft ...... 858 CGContext-Klasse ...... 702, 1174 Trailing Closures ...... 155 Data-Source-Protokoll ...... 656 Container (CloudKit) ...... 889 CGContextAddArc-Methode ...... 695 UIAlert-Beispiel ...... 504 NSTableView ...... 652 Containment Segues ...... 521 CGContextDrawPath-Methode ...... 695 unowned self ...... 161, 707 UITableView ...... 632 contains-Methode ...... 173, 219, 230, 232, 738 CGFloat-Datentyp ...... 172 verzögert ausführen ...... 925, 1133 Data-Struktur ...... 201, 602, 1081 Content Compression ...... 428 CGFloat-Typ ...... 397 weak ...... 161 dataEncodingStrategy-Eigenschaft ...... 615 Content Compression Resistance Priority ...... 438 CGImage-Klasse ...... 1174 Cloud (iCloud) ...... 875 dataSource-Eigenschaft Content Hugging ...... 428 CGImageDestination-Klasse ...... 1175 CloudKit ...... 876, 888 NSTableView ...... 652 contentMode-Eigenschaft ...... 716 CGImageDestinationFinalize-Funktion ...... 1175 CMCoreMotionManager-Klasse ...... 827 UICollectionView ...... 666 eigene Steuerelemente ...... 698 CGMotion-Klasse ...... 830 CMTime-Struktur ...... 769, 780 UIPickerView ...... 1120 Image-View ...... 431, ...... 457 cgPath-Eigenschaft ...... 860 cmysql-Bibliothek ...... 1026 UITableView ...... 631 contentOverlayView-Eigenschaft ...... 771 CGPoint-Struktur ...... 171, 719 Cocoa Touch ...... 409 date-Methode contents-Eigenschaft ...... 735 erweitern ...... 176 Cocoa-Framework ...... 508 Calendar ...... 205 589 CGRect-Struktur ...... 171, 658, 719 CocoaPods ...... 361 contentsOfDirectory-Methode ...... DateFormatter ...... 204 120 erweitern ...... 175 YouTube-Beispiel ...... 785 continue-Schlüsselwort ...... Date-Struktur ...... 203 800 CGSize-Struktur ...... 171, 719 Codable-Protokoll ...... 614, 1080 continuousAutoFocus-Enumerationswert ...... tvOS-Beispiel ...... 558 812 1196 CGVector-Struktur ...... 171 CodingKeys-Enumeration (JSON) ...... 617 Control Center ...... , dateEncodingStrategy-Eigenschaft ...... 615 720 changeCurrentDirectoryPath-Methode ...... 588 Collection-View-Steuerelement ...... 661 control-Eigenschaft ...... dateFormat-Eigenschaft ...... 203 376 changeFont-Methode ...... 536 Beispiel zur Farbauswahl ...... 886 Controller ...... DateFormatter-Klasse ...... 203 1022 Character-Datentyp ...... 179 Foto-App ...... 797 Vapor ...... Dateien ...... 577 830 characters-Eigenschaft ...... 540 Hintergrund unsichtbar ...... 797 controllers-Eigenschaft ...... auswählen ...... 533 268 CharacterSet-Struktur ...... 187 collisionBitMask-Eigenschaft ...... 844, 857 Convenience Init Function ...... Eigenschaften ermitteln ...... 590 childNode-Methode ...... 870, 1276 Color Panel ...... 537 Vererbung ...... 293 Größe ermitteln ...... 590 children-Eigenschaft ...... 332 Color Well ...... 537 convenience-Schlüsselwort ...... 268 kopieren ...... 593 CKAccountChanged-Notification ...... 897 color-Eigenschaft ...... 537 convert-Methode ...... 720, 735, 1185 löschen ...... 593 CKAsset-Klasse ...... 898 SpriteKit ...... 815 Fonts ...... 536 temporäre Datei ...... 588 CKContainer-Klasse ...... 896, 903 colorBlendFactor-Eigenschaft ...... 815 Copy-on-Write (Zeichenketten) ...... 183 testen, ob Datei existiert ...... 583 CKModifyRecordOperation-Klasse ...... 898 command-Eigenschaft ...... 720 copyItem-Methode ...... 593 Textdateien lesen/schreiben ...... 595 CKQuery-Klasse ...... 900 CommandLine-Enumeration ...... 35 Core Data ...... 590 URLs ...... 582 CKQueryOperation-Klasse ...... 900 Comparable-Protokoll ...... 318 Core Graphics ...... 702 verschieben ...... 593 CKRecord-Klasse ...... 898, 900 compare-Methode ...... 186 Core Libraries ...... 992 Dateisystem (Größe ermitteln) ...... 560

1284 1285

“buch”—2017/10/6—8:49—page1286—#1282 “buch” — 2017/10/6 — 8:49 — page 1287 — #1283

Index Index

Datenbanken density-Eigenschaft ...... 857 do-Schlüsselwort (try-catch) ...... 338 E ...... 890 ...... 1036 Docker ...... 989 CloudKit Deployment (Vapor) EAN8/EAN13-Barcode ...... 800 ...... 1017 ...... 632 635 Vapor ...... 1003 Vapor/Fluent dequeueReusableCell-Methode , Edges (SpriteKit) ...... 856 ...... 980 Document-Outline-Seitenleiste ...... 394 Datenquelle im Connections Inspector DerivedData-Verzeichnis Eigenschaften ...... 254 einstellen ...... 631, 652 314 1080 documentDirectory-Konstante ...... 587 description-Eigenschaft ...... , beobachten ...... 257 Datensatz speichern (CloudKit) ...... 898 268 Dokumentenbasierte Apps ...... 877 Designated Init Function ...... Computed Properties ...... 259 Datentypen ...... 104 293 domain-Eigenschaft ...... 356 Vererbung ...... Extensions ...... 327 Aliasse ...... 281 679 Doppelgänger im Array entfernen ...... 226 desiredAccuracy-Eigenschaft ...... Fehler auslösen ...... 349 ermitteln ...... 78, 331 467 Doppelte Optionals ...... 343 destination-Eigenschaft ...... Read-Only-Eigenschaft ...... 261 Funktionstypen ...... 150 754 Double-Datentyp ...... 166 destinationIndexPath-Eigenschaft ...... statische Eigenschaften ...... 259 Datum ...... 203 636 Double-Init-Funktion ...... 200 detailTextLabel-Eigenschaft ...... Zugriff mit Optional Chaining ...... 103 deadline-Parameter ...... 925, 1133 22 399 Downcast ...... 78, 297, 331 Developer Program ...... , Zugriff per KeyPath ...... 333 decimalSeparator-Eigenschaft ...... 1117 891 Downloads per HTTP/HTTPS ...... 601 Development Environement (CloudKit) ...... Eingabefokus einstellen ...... 1069 Decodable-Protokoll ...... 614 825 einer inaktiven App fortsetzen ...... 605 Device Orientation ...... Einstellungen (iOS) öffnen ...... 896 decode-Methode ...... 621 827 im Hintergrund ...... 604 deviceMotionUpdateInterval-Eigenschaft ...... Einstellungen (macOS) ...... 526 default-Schlüsselwort (switch) ...... 113 795 downloadsDirectory-Konstante ...... 587 devices-Eigenschaft ...... element-Methode ...... 610 defaultManager-Methode ...... 1190 825 downloadTask-Methode ...... 606 Devie Orientation ...... else-Schlüsselwort ...... 107 DefaultPrecedence (Operatoren) ...... 86 226 Drag & Drop ...... 728 Dictionaries ...... guard ...... 110 581 316 Dateinamen empfangen ...... 737, 1186 defaults-Kommando ...... Dictionary-Datentyp (Hashable) ...... Emitter (SpriteKit) ...... 872 144 845 1204 Dateinamen senden ...... 1185 Defaultwerte für Parameter ...... didBegin-Methode (Kollisionen) ...... , Encodable-Protokoll ...... 614 132 851 iOS ...... 742 defer-Schlüsselwort ...... Luftballon-Beispiel ...... encode-Methode ...... 615, 621 344 macOS ...... 728 in try-catch-Konstruktionen ...... Pac-Man ...... 1245 endedAtPoint-Parameter ...... 730 271 282 UITableView-Steuerelement ...... 749 Deinit-Funktion ...... , didChangeExternallyNotification-Konstante ... 883 endEditing-Methode ...... 450, 1118 74 weitergeben ...... 1178 Dekrement-Operator ...... didEnd-Methode (Kollisionserkennung) ...... 845 endIndex-Eigenschaft ...... 193 1133 Zeichenkette empfangen ...... 737 delay-Funktion ...... didFinishDownloadingTo-Parameter ...... 606 endRefreshing-Methode ...... 649 Zeichenkette senden ...... 735 delegate-Eigenschaft didFinishProcessingPhotoSampleBuffer- enum-Schlüsselwort ...... 97 775 796 dragDelegate-Eigenschaft ...... 751 AVAudioRecorder ...... Parameter ...... Beispiele ...... 1130 679 473 729 1187 CLLocationManager ...... didMove-Methode ...... draggingEntered-Methode ...... , Enumerationen 679 411 draggingExited-Methode ...... 729, 741 MKMapView ...... didReceiveMemoryWarning-Methode ...... als Datentypen ...... 250 531 1124 draggingPasteboard-Methode ...... 740 NSApplicationDelegate ...... didSelectRow-Parameter ...... Associated Values ...... 252 536 257 290 1062 1114 draggingSession-Methode ...... 730, 736, 1185 NSFontManager ...... didSet-Funktion ...... , , , Beispiel ...... 1171 652 1184 694 1153 draggingUpdated-Methode ...... 729 NSTableView ...... , Beispiel ...... , Beispiele ...... 1130 416 568 571 1278 dragInteraction-Methode ...... 743, 746 UIApplication ...... didUpdateFocus-Methode ...... , , indirekt/rekursiv ...... 253 1120 669 drand48-Funktion ...... 169, 1134 UIPickerView ...... Trailer-Beispiel ...... zur Definition von Konstanten ...... 97 495 502 131 364 draw-Funktion ...... 1174 UIPopoverPresentationController ...... , discardableResult-Attribut ...... , Ephemeral-Konfiguration (URLSession) ...... 605 631 903 draw-Methode ...... 541, 722, 1173 UITableView ...... discoverUserIdentity-Methode ...... equalTo-Methode ...... 173 1118 968 5-Gewinnt-Beispiel ...... 1149 UITapGestureRecognizer ...... Disk-Image ...... Equatable-Protokoll ...... 316, 325 Drag-und-Drop-Beispiel ...... 733 UITextField ...... 450, 1117 dismiss-Methode ...... 503, 523 als Extension implementieren ...... 324 Grafikprogrammierung ...... 689 Delegation ...... 304, 405, 449 dismissController ...... 524 Erdbeschleunigung ...... 828 Hintergrundfarbe ...... 693 Beispiel für eigenes Delegation-Protokoll .... 1097 dismissViewControllerAnimated-Methode .... 1161 Error-Protokoll ...... 354 drawRect-Methode ...... 1086 CLLocationManagerDelegate-Beispiel ...... 678 Dispatch-Framework ...... 919 escaping-Attribut ...... 162, 364 drawsBackground-Eigenschaft ...... 658 im Connections Inspector einstellen ...... 631, 652 DispatchGroup-Klasse ...... 924 Eulersche Zahl ...... 148 dRnd-Funktion ...... 847 NSTableView ...... 652, 656 DispatchQoS.QoSClass-Enumeration ...... 924 Exceptions ...... 337, 349 drop-Methode ...... 219 SetPieceDelegate-Beispiel ...... 1145 DispatchQueue-Klasse ...... 922, 925, 1133 exit-Funktion ...... 565 dropDelegate-Eigenschaft ...... 751 UITableView ...... 631 Code im Main-Thread ausführen ...... 609 Exit-Icon (ViewController) ...... 463 Dropdown-Liste ...... 1119 UITextFieldDelegate-Beispiel ...... 450 Trailer-Beispiel ...... 666 Exponential-Operator ...... 89 dropFirst-Methode ...... 218 delete-Methode (Vapor) ...... 1008 DispatchTime-Klasse ...... 925, 1133 ExpressibleByStringLiteral-Protokoll ...... 320 dropInteraction-Methode ...... 743, 747 Delete-on-Swipe (UITableView) ...... 1067 distanceFromLocation-Methode ...... 1096 Extended Grapheme Cluster ...... 183 dropLast-Methode ...... 218 deleteRows-Methode ...... 1067 distanceTo-Methode ...... 176 Extensions ...... 322 Droplet-Klasse (Vapor) ...... 1006 deleteSelf-Konstante ...... 899 Distribution Provisioning Profile ...... 956 Beispiele ...... 1132 dropSessionDidUpdate-Parameter ...... 753 deleteXxx-Methoden (NSEvent) ...... 540 distribution-Eigenschaft ...... 436 bequemer Zeichenkettenzugriff ...... 195 dynamic-Schlüsselwort ...... 248 deletingLastPathComponent-Methode ...... 583 Division durch null ...... 74 eigene map-Methode ...... 352 deletingPathExtension-Methode ...... 583 DMG-Datei erstellen ...... 968 Protokolle ...... 328

1286 1287

“buch” — 2017/10/6 — 8:49 — page 1288 — #1284 “buch” — 2017/10/6 — 8:49 — page 1289 — #1285

Index Index

F Tastatur (iOS) ...... 452 Namen ...... 134 Grand Central Dispatch (GCD) ...... 919 Tastatur (macOS) ...... 538 optionale ...... 310 gravity-Eigenschaft ...... 828, 841, 855, 858, 1269 Fünf-Gewinnt-App ...... 1127 first-Eigenschaft ...... 193, 211, 218 Parameter ...... 138 group-Methode (SpriteKit-Aktionen) ...... 835 Fade-In-Effekt ...... 708 first-Methode (Vapor/Fluent) ...... 1021 Rückgabewert ...... 129 groupingSeparator-Eigenschaft ...... 1115 fadeAlpha-Methode ...... 833 Fixed Sized Arrays ...... 216 Rückgabewert ignorieren ...... 131 Grundrechenarten ...... 73 fadeIn-Methode ...... 833 Fixed-width-constraints-Warnung ...... 431 Standardfunktionen ...... 145 guard-Schlüsselwort ...... 110, 349 fadeOut-Methode ...... 833 flagsChanged-Methode ...... 539 verschachtelte Funktionen ...... 135 Gyroskop ...... 825 Failable Init Functions ...... 269 flashMode-Eigenschaft ...... 796 verzögert ausführen ...... 925, 1133 gyroUpdateInterval-Eigenschaft ...... 827 fallthrough-Schlüsselwort (switch) ...... 113 flatMap-Methode ...... 221 Funktionsabschluss (Closure) ...... 154 false ...... 170 Fließkommazahlen ...... 166 H familyName-Eigenschaft ...... 903 FloatingPoint-Protokoll ...... 167 Farb-Literale ...... 811 G Half-Open-Range-Operator ...... 80 Fluent-Bibliothek (Vapor) ...... 1017 Farben Hash-Code (Vapor) ...... 1035 fluent.json-Datei (Vapor) ...... 1025 Gültigkeitsebenen 227 316 abdunkeln ...... 1132 135 Hashable-Protokoll ...... , Focus Engine (Apple TV) ...... 567 Funktionen ...... 748 auswählen ...... 533 248 hasItemsConforming-Methode ...... Asteroids-Beispiel ...... 1273 Klassen ...... 185 aufhellen ...... 1132 838 hasPrefix-Methode ...... focusMode-Eigenschaft ...... 800 Game-Loop (SpriteKit) ...... 185 1191 Fatal Error ...... 337 830 1269 hasSuffix-Methode ...... , Fokus-Einstellung (Kamera) ...... 800 GameController-Bibliothek ...... , 1096 fatalError-Funktion ...... 137 1242 Haversine-Formel ...... follow-Methode ...... 832 GameKit-Bibliothek ...... 972 Fehler 166 Header-Code erzeugen ...... Font auswählen ...... 533 Ganze Zahlen ...... 337 height-Eigenschaft ...... 719 Absicherung ...... 536 Garbage Collector ...... 282 Font Manager ...... heightForRowAt-Parameter ...... 644 auslösen (throw) ...... 346 Font Panel ...... 536 Gatekeeper ...... 965 338 heightOfRow-Parameter ...... 657 do-try-catch ...... 532 GCController-Klasse ...... 830, 1269 Font-Attribute ändern ...... Heimatverzeichnis ...... 587, 1254 NSError-Klasse ...... 355 font-Eigenschaft ...... 397 Generalisierung ...... 297 342 Hello World Weitergabe ...... 117 ...... 972 for-in-Schleife ...... Generated Interface Animationen ...... 706 Fenster 343 299 Forced Try ...... Generics ...... iCloud ...... 882 ausblenden ...... 554 712 216 forces-Eigenschaft ...... Array-Beispiel ...... iOS-App ...... 374 Größe fixieren ...... 512, 524 222 324 forEach-Methode ...... Extensions ...... iOS-App mit Popup ...... 493 in den Vordergrund bringen ...... 553 312 Foreign-Key-Fehler (MySQL) ...... 1025 Protokolle ...... Linux ...... 988 per Code erzeugen ...... 525 302 Formatieren Type Constraints ...... macOS-Programm ...... 507 schließen ...... 524 725 Datum und Uhrzeit ...... 203 Gesture Recognizer ...... MapView/GPS ...... 671 Fernbedienung (Apple TV) ...... 561, 1260 1062 1064 Zahlen ...... 199 Long Press ...... , Package Manager ...... 993 fetchUserRecordID-Methode ...... 903 1118 Fotos Tap ...... Playground ...... 21 591 567 FileAttributeKey-Struktur ...... aus der Camera-Roll auswählen ...... 788 tvOS ...... Script ...... 38 591 fileExists-Methode ...... in einer Capture-Session aufnehmen ...... 791 get-Methode (Vapor) ...... 1008 Terminal App ...... 31 1190 fileExistsAtPath-Methode ...... mit der Picker-View aufnehmen ...... 790 get-Schlüsselwort ...... 96, 259, 279 Vapor (Server-side Swift) ...... 996 587 FileManager-Klasse ...... Foundation-Framework ...... 33 getifaddrs-Funktion ...... 365 Hexadezimale Zahlen ...... 166 590 Dateioperationen ...... frame-Eigenschaft ...... 433, 658, 719, 735 GIMP (Parallax-Icons) ...... 942 Hide-Bars-On-Swipe-Option ...... 645 587 Standardverzeichnisse ermitteln ...... SKNode-Klasse ...... 840 Git ...... 973, 996 HIG (Human Interface Guidelines) ...... 938, 942 247 fileprivate-Schlüsselwort ...... Frameworks ...... 359 givenName-Eigenschaft ...... 903 higherThan-Schlüsselwort (Operatoren) ...... 89 900 fileURL-Eigenschaft (CloudKit) ...... Server-side Swift ...... 986 GKGridGraph-Klasse ...... 1242 Highscore speichern (Asteroids-Spiel) ...... 1272 fileURL-Konstante ...... 732 Xcode ...... 675 GKInspectable-Attribut ...... 364 Hintergrund-App ...... 677, 763 fill-Methode ...... 691, 1086 Free Provisioning ...... 398 Globale Funktionen ...... 145 Hintergrundfarbe von Fenster (macOS) ...... 888 fillColor-Eigenschaft ...... 816 friction-Eigenschaft ...... 1201 Globale Queues ...... 923 Homebrew-Paketmanager ...... 968, 995 filter-Methode ...... 187, 220 front-Enumerationswert ...... 790 Gomoku ...... 1127 horizontalAlignmentMode-Eigenschaft ...... 818 Dictionaries ...... 230 Front-Kamera ...... 795 GPS-Funktionen ...... 671 HTTP(S)-Dokument laden ...... 601 Fluent-Datensätze ...... 1021 func-Schlüsselwort ...... 127 Grafikprogrammierung ...... 687 HTTP-Requests ...... 1000 Sets ...... 231 Funktionale Programmierung ...... 149 Drag & Drop (UIBezierPath) ...... 733 HTTPS (Vapor) ...... 1036 602 final-Schlüsselwort ...... 248, 293 Funktionen ...... 127 in einer MapView (MK-Methoden) ...... 680 HTTPS-Probleme mit NSURL ...... 938 942 finally-Schlüsselwort ...... 344 als Parameter ...... 151 Hockey-Spieler zeichnen ...... 541 Human Interface Guidelines ...... , find-Methode (Vapor/Fluent) ...... 1021 als Rückgabewert ...... 152 Kompass-Steuerelement ...... 694 Finder per Code anzeigen ...... 1179 Funktionstypen ...... 150 Kreise zeichnen (UIBezierPath) ...... 720 First Responder ...... 544, 1069 Gültigkeitsebenen ...... 135 Objekt ausschneiden ...... 1253 Menüs ...... 546 globale Funktionen ...... 145 Steuerelement zur Richtungsanzeige ...... 1086

1288 1289

“buch”—2017/10/6—8:49—page1290—#1286 “buch” — 2017/10/6 — 8:49 — page 1291 — #1287

Index Index

I Init-Funktion ...... 244, 266 iso8601-Konstante (JSONEncoder) ...... 615 Kontextmenü ...... 550 Designated versus Convenience ...... 268 isPaused-Eigenschaft ...... 837 Koordinatensystem ...... 718 IBAction-Attribut ...... 364, 383 ...... 250 isReadableFile-Methode ...... 591 Kreis zeichnen ...... 722, 1253 IBDesignable-Attribut ...... 364, 701 Enumeration 347 isResting-Eigenschaft ...... 857 Kreiselkompass ...... 825 IBInspectable-Attribut ...... 364, 701 Fehler auslösen (throw) ...... 269 isSourceTypeAvailable-Methode ...... 781 Kreisteilungszahl ...... 148 IBOutlet-Attribut ...... 364, 383 nil zurückgeben ...... 268 isUserInteractionEnabled-Eigenschaft ...... 745 kUTTypeImage-Konstante ...... 748 iCloud ...... 875 Overloading ...... 296 isViewLoaded-Methode ...... 481 kUTTypeMovie-Konstante ...... 781 iCloud Drive ...... 877 Redundanz vermeiden ...... 412 isWritableFile-Methode ...... 591 iCloud-ID ermitteln ...... 903 UIViewController ...... 753 881 Vererbung ...... 293 itemsForAddingTo-Parameter ...... L Key/Value-Speicher ...... 746 753 1070 initRnd-Funktion ...... 847 itemsForBeginning-Parameter ...... , Key/Value-Speicher (To-do-App) ...... 956 Label 1165 Inkrement-Operator ...... 74 iTunes Connect ...... Icon ...... macOS ...... 512 938 inout-Schlüsselwort ...... 142 App ...... SpriteKit ...... 818 961 insert-Methode ...... 213, 230 J iTunes Connect ...... Sprunglabel (break/continue) ...... 120 1165 insertContentOf-Methode ...... 213 503 Resizer ...... Ja/Nein-Dialog ...... Lambda-Ausdruck ...... 154 535 insertRows-Methode ...... 1066 192 224 icon-Eigenschaft (NSAlert) ...... joined-Methode ...... , Landscape-Modus ...... 825 1171 insertText-Methode ...... 540 225 IconSize-Struktur (Icon-Resizer-Beispiel) ...... JoinedSequence-Struktur ...... last-Eigenschaft ...... 193, 211, 218 319 insertXxx-Methoden (NSEvent) ...... 540 614 id-Datentyp (Objective-C) ...... JSON ...... lastPathComponent-Eigenschaft ...... 583 891 instantiateController-Methode ...... 525 614 ID-Nummer (CloudKit) ...... Codable-Protokoll ...... Launch Image (tvOS) ...... 946 1031 instantiateViewController-Methode ...... 499 1011 Identifier-Klasse (Vapor) ...... Vapor ...... launch-Methode ...... 369 115 Instanzmethoden ...... 271 616 1081 if-available-Test ...... JSONDecoder-Klasse ...... , launchApplication-Methode ...... 621 108 Int-Datentyp ...... 166 1046 if-let-Konstruktion ...... NYT-Beispiel ...... launchPath-Eigenschaft ...... 369 Int-Init-Funktion ...... 199 615 1081 Kaskaden ...... 109 JSONEncoder-Klasse ...... , LaunchScreen-Datei ...... 939 Interface ...... 304 kombiniert mit Bedingungen ...... 110 Lautstärke ändern ...... 761 383 if-Verzweigungen ...... 107 Interface Builder ...... K Layer ...... 778 102 108 740 Interface Orientation ...... 825 let (Optionals) ...... , , Kürzester-Pfad-Problem ...... 1242 layer-Eigenschaft ...... 888, 1150 659 705 735 internal-Schlüsselwort ...... 247 image-Eigenschaft ...... , , Kamera wechseln ...... 795 Layered Image File Format ...... 942 781 788 Internationalization (i18n) ...... 947 Image-Picker-Controller ...... , Kanonenkugel (Beispiel) ...... 858 Layout Guides ...... 432 642 1104 Internet-Radio abspielen ...... 769 Image-View-Steuerelement ...... , Key/Value-Paare ...... 226 layoutFrame-Eigenschaft ...... 809, 1197 Interpolation (Strings) ...... 197 imageComponentsProvider- iCloud ...... 876, 881 layoutMargins-Eigenschaft ...... 809 735 1185 interpretKeyEvents-Methode ...... 540 Eigenschaft ...... , iCloud (To-do-App) ...... 1070 Layoutregeln ...... 417 811 738 imageLiteral-Schlüsselwort ...... intersect-Methode ...... keyCode-Eigenschaft ...... 540 Hoch- und Querformat ...... 445 455 173 840 Images.xcassets-Datei ...... intersects-Methode ...... , keyDown-Methode ...... 539 je nach Device variieren ...... 440 639 926 UIImage-Objekt erzeugen ...... invalidate-Methode ...... KeyedDecodingContainer ...... 621 Varianten ...... 440 636 imageView-Eigenschaft (UITableCell) ...... iOS KeyPath-Ausdrücke ...... 333 Lazy Properties ...... 255 980 Implicitly Unwrapped Optionals ...... 101 DeviceSupport-Verzeichnis ...... keys-Eigenschaft ...... 229 Beispiel ...... 605 403 import-Anweisung ...... 359 Grundlagen ...... keyUp-Methode ...... 539 lazy-Eigenschaft ...... 215 374 in-Schlüsselwort (Closures) ...... 154 Hello World ...... Kitura-Framework ...... 986 LazyMapCollection-Datentyp ...... 229 378 675 include-Anweisung (Bridging-Datei) ...... 366 Simulator ...... , Klassen ...... 242 LCR-Datei ...... 942 559 Index-Datentyp ...... 188 Versionsnummer ermitteln ...... verschachteln ...... 249 Lebenszyklus 365 Zeichenketten ...... 193 IP-Adresse ermitteln ...... Kollisionserkennung ...... 840 App ...... 414 index-Methode ...... 219 iPhone X Luftballone ...... 845 View-Controller ...... 410 432 Zeichenketten ...... 193, 194 Safe Area Layout Guides ...... Pac-Man ...... 1245 Left-Shift (bitweises Rechnen) ...... 75 IndexPath-Klasse ...... 647 SpriteKit ...... 809 Kommandoparameter ...... 35 leftBarButtonItem-Eigenschaft ...... 492 indexPath-Methode ...... 647, 1091 iRnd-Funktion ...... 847 Kommentare ...... 43 leftItemsSupplementBackButton-Eigenschaft 492 indexPathForCell-Methode ...... 647 is-Operator ...... 78, 298, 331 MARK ...... 733 let-Schlüsselwort ...... 94 indices-Eigenschaft ...... 223 isBezeled-Eigenschaft ...... 658 Playground ...... 28 in switch-Konstruktionen ...... 114 indirect-Schlüsselwort ...... 253 isDeletableFile-Methode ...... 591 Kompass ...... 671, 683 mit if ...... 108, 740 infinity-Eigenschaft ...... 74 isDynamic-Eigenschaft ...... 857 Kalibrierung ...... 684 mit switch-case ...... 252 infix-Schlüsselwort ...... 88 SpriteKit ...... 844 Komplexe Zahlen (Operator-Beispiel) ...... 87 mit while ...... 119 Info.plist-Datei ...... 940 isEditable-Eigenschaft ...... 658 Konstanten ...... 94 letters-Eigenschaft ...... 187 ändern (App Transport Security) ...... 626 isEmpty-Eigenschaft ...... 211, 229 Eigenschaften ...... 255 limit-Methode (Vapor/Fluent) ...... 1021 Privacy-Einträge (Standortzugriff) ...... 673 isEnabled-Eigenschaft ...... 1063 Eulersche Zahl ...... 148 line-Methode ...... 691 Privacy-Einträge (Video-Zugriff) ...... 781 isMultipleTouchEnabled-Eigenschaft ...... 713, 819 Pi ...... 148 linearDamping-Eigenschaft ...... 857, 1201

1290 1291

“buch”—2017/10/6—8:49—page1292—#1288 “buch”—2017/10/6—8:49—page1293—#1289

Index Index

lineWidth-Eigenschaft ...... 722 mass-Eigenschaft ...... 857 Module ...... 246, 359 nonConformingFloatEncodingStrategy- SpriteKit ...... 816 Master-Ansicht zuerst anzeigen ...... 490 Modulo-Operator ...... 73 Eigenschaft ...... 615 137 Listen-Steuerelement (iOS) ...... 629 Mathematische Funktionen ...... 148 motion-Eigenschaft ...... 830 noreturn-Attribut ...... 1083 veränderliche Listen ...... 647 Maus ...... 718 mouseDown-Methode ...... 718, 724, 1185 Notification Center ...... Picker-View ...... 1119 max-Eigenschaft ...... 166 mouseDragged-Methode ...... 718, 735, 1185 AVPlayer ...... 769 LiteralConvertible-Protokolle ...... 320 max-Funktion ...... 147 mouseEntered-Methode ...... 718 Layout ändern ...... 447 loadObjects-Methode ...... 748, 754 maximumFractionDigits-Eigenschaft ..... 199, 1115 mouseExited-Methode ...... 718 NotificationCenter-Klasse ...... 1084 loadRequest-Methode ...... 622, 1052 maxPoint-Eigenschaft ...... 175 mouseUp-Methode ...... 718 notify-Methode ...... 924 locale-Eigenschaft ...... 199, 203 maxX/maxY-Eigenschaft ...... 173 move-Methode ...... 691 nowPlayingInfo-Eigenschaft ...... 765 968 Locale-Struktur ...... 199, 203 Maze-Klasse (Pac-Man-Spiel) ...... 1220 SpriteKit ...... 832 npm-Kommando ...... 534 im Playground ...... 198 MediaPlayer-Bibliothek ...... 758, 761 moveItem-Methode ...... 593 NSAlert-Klasse ...... 517 1179 Localization (l10n) ...... 947 mediaTypes-Eigenschaft ...... 781 moveRowAt-Parameter ...... 1067 NSApplication-Klasse ...... , Localization native development region ...... 948 Mehrblättrige Dialoge ...... 526 moveXxx-Methoden (NSEvent) ...... 540 NSAppTransportSecurity-Eintrag ...... 602 localizedCaseInsensitiveCompare ...... 186 Mehrdimensionale Arrays ...... 216 Movie-Trailer-Beispiel ...... 661 NSBezierPath-Klasse ...... 722, 733, 1253 356 localizedDescription-Eigenschaft ...... erzeugen ...... 1132 MP3/MP4-Format ...... 759 NSBitmampImageRep-Klasse ...... 1254 678, 679 Location Manager ...... Mehrfachvererbung ...... 288 MPMedia-Konstanten ...... 765 NSButton-Klasse ...... 1189 683 204 Kompass ...... Menüs ...... 543 MPNowPlayingInfoCenter-Klasse ...... 764 NSCalendar-Klasse ...... 1082 783 788 teilen ...... deaktivieren ...... 552 MPRemoteCommandCenter-Klasse ...... 764 NSCameraUsageDescription-Key ...... , 712 356 location-Methode ...... Kontextmenüs ...... 550 MPVolumeView-Klasse ...... 761 NSCocoaErrorDomain ...... 1153 412 locationInView-Methode ...... menu-Eigenschaft Multi-Threading ...... 919 NSCoding-Protokoll ...... 720 locationInWindow-Eigenschaft ...... NSApplication ...... 550 Multiple-Touch-Option ...... 713 NSColorPanel-Klasse ...... 537 680 683 locationManager-Methode ...... , NSView ...... 550 mutating-Schlüsselwort ...... 273 NSColorWell-Steuerelement ...... 537 locationManagerShouldDisplayHeading- Menubar-App ...... 552 MySQL (Vapor) ...... 1026 NSData-Klasse ...... 201 Calibration-Methode ...... 684 203 Message-Box ...... 533 mysql.json-Datei (Vapor) ...... 1026 NSDate-Klasse ...... 1173 lockFocus-Methode ...... messageText-Eigenschaft ...... 534 NSDictionary-Klasse ...... 530 ...... 800 lockForConfiguration-Methode metadataOutput-Methode ...... 802 NSDraggingDestination-Protokoll ...... 729 ...... 80 N logische Operatoren Metal ...... 803 NSDraggingImageComponent-Klasse ...... 735 Lottozahlen ...... 231 Metatypen ...... 334 Nachkommaanteil ...... 1215 NSDraggingInfo-Klasse ...... 740 Benchmarks ...... 235 Methoden ...... 271 Nachrichten anzeigen ...... 533 NSDraggingItem-Klasse ...... 730, 735, 1185 macOS-Beispiel ...... 509 Aufruf mit Optional Chaining ...... 103 Namenlose Parameter ...... 139 NSDraggingSource-Protokoll ...... 735, 1185 lowercased-Methode ...... 186 Mutating Methods ...... 273 Navigation-Controller ...... 471 NSError-Klasse ...... 355 LSR-Datei ...... 942 optionale ...... 310 Navigation per Code ...... 474 NSEvent-Klasse Signatur ...... 276 Beschriftung ändern ...... 474 Maus ...... 720 M statische Methoden ...... 275 Detailansicht einer Liste ...... 644 Tastatur ...... 540 485 491 720 Main Queue ...... 923 Typmethoden ...... 275 mit Split-View-Controller ...... , NSEventModifierFlags-Struktur ...... 479 349 main-Methode (Dispatch Queue) ...... 923 middlePoint-Eigenschaft ...... 175 mit Tab-Bar-Controller ...... NSException-Klasse ...... 1049 1190 makeImage-Funktion ...... 1174 midX/midY-Eigenschaft ...... 173 weißer Streifen ...... NSFileManager-Klasse ...... 492 740 makeJSON-Methode (Vapor) ...... 1012 Mikrofon (Audio-Aufnahmen) ...... 772 navigationItem-Eigenschaft ...... NSFilenamesPboardType-Konstante ...... 919 532 makeKeyAndOrderFront-Eigenschaft ...... 553 min-Eigenschaft ...... 166 Nebenläufige Programmierung ...... NSFont-Klasse ...... makeQuery-Methode (Vapor/Fluent) ...... 1021 min-Funktion ...... 147 Nested Functions ...... 135 NSFontManager-Klasse ...... 532, 536 map ...... 81 minimumFractionDigits-Eigenschaft ...... 199, 1115 Nested Generics ...... 300 NSFontPanel-Klasse ...... 536 Map Kit (MK) ...... 671 minimumPressDuration-Eigenschaft ...... 1062 Never-Schlüsselwort ...... 137 NSGestureRecognizer-Klasse ...... 725 Framework ...... 675 minPoint-Eigenschaft ...... 175 New York Times (Beispiel-App) ...... 1043 NSGradient-Klasse ...... 1253 map-Methode minX/minY-Eigenschaft ...... 173 nextCommand-Eigenschaft ...... 766 NSHomeDirectory-Funktion ...... 587, 1254 rethrows-Beispiele ...... 350 Mirror-Datentyp ...... 332 nextFocusedItem-Eigenschaft ...... 571 NSImage-Klasse ...... 659, 1173 Sets ...... 231 MKMapView-Klasse ...... 671 NextStep ...... 27 Assets verwenden ...... 585 mapOverlay-Methode ...... 680 MKMapViewDelegate-Protokoll ...... 678 nginx-Webserver (Vapor) ...... 1038 NSImageView-Klasse ...... 733 mapValues-Methode (Dictionaries) ...... 230 MKPolyline-Klasse ...... 680 NIB-Datei ...... 412 NSImageView-Steuerelement ...... 659 mapView-Methode ...... 682 MKPolylineRenderer ...... 682 Nil ...... 84 NSItemProvider-Klasse ...... 743, 746, 753 MapView-Steuerelement ...... 671 MobileCoreServices-Bibliothek ...... 781 Nil-Coalescing-Operator ...... 84 NSItemProviderReading-Protokoll ...... 748 MariaDB (Vapor) ...... 1028 Model-Protokoll (Vapor/Fluent) ...... 1017 nil-Schlüsselwort ...... 99 NSLayoutConstraint-Klasse ...... 434 MARK-Kommentar ...... 45, 733 modifierFlags-Eigenschaft ...... 540, 720 nil-Test ...... 102 NSLocale-Klasse ...... 186 Markdown-Kommentare ...... 28, 43 Modifizier ...... 248 noescape-Attribut ...... 162 NSLocalizedString-Klasse ...... 954

1292 1293

“buch” — 2017/10/6 — 8:49 — page 1294 — #1290 “buch” — 2017/10/6 — 8:49 — page 1295 — #1291

Index Index

NSMakeRange-Funktion ...... 189 NSWindow-Klasse ...... 508, 512 OptionSet-Protokoll ...... 231 perform-Methode ...... 900 NSManaged-Attribut ...... 365 NSWindowController-Klasse ...... 508 Beispiel ...... 720 performDragOperation-Methode .... 730, 741, 1187 NSMenu-Klasse ...... 545 NSWorkspace-Klasse ...... 621, 1179 orderFrontFontPanel-Methode ...... 536 performDrop-Parameter ...... 748 NSMenuItem-Klasse ...... 545 NSxxx-Klassennamen ...... 27 orderOut-Methode ...... 554 performDropWith-Parameter ...... 754 NSMenuValidation-Protokoll ...... 550 null-Schlüsselwort ...... 99 orientation-Eigenschaft ...... 447 performSegue-Methode ...... 469, 525 NSMicrophoneUsageDescription-Key ...... 783 NumberFormatter-Klasse ...... 199, 200, 1115 origin-Eigenschaft ...... 719 Navigation-Controller ...... 474 NSMutableDictionary-Klasse ...... 1111 numberFromString-Methode ...... 200 os-Test ...... 116 permittedArrowDirections-Eigenschaft ...... 498 NSNumber-Klasse ...... 170 numberOfComponents-Methode ...... 1121 Outlets ...... 382, 405 Photo Library ...... 788 Beispiel Dateigröße ...... 591 numberOfLoops-Eigenschaft ...... 760 Collections ...... 386 photoOutput-Methode ...... 796 NSNumberFormatter-Klasse ...... 657, 1117 numberOfMatches-Methode ...... 189 macOS ...... 515 physicalMemory-Eigenschaft ...... 559 NSObject-Klasse ...... 288, 656 numberOfRowsInComponent-Parameter ...... 1121 umbenennen ...... 386 physicsBody-Eigenschaft ...... 842 description-Eigenschaft ...... 315 numberOfRowsInSection-Parameter ...... 632 outputFormatting-Eigenschaft ...... 615 physicsWorld-Eigenschaft ...... 841 NSObject-Protokoll ...... 1083 numberOfRowsInTableView-Methode ...... 652 Overloading Physik (SpriteKit) ...... 852 632 NSObjectProtocol-Protokoll ...... 288, 1083 numberOfSectionsInTableView-Methode ...... Funktionen ...... 134 Pi-Konstante ...... 148 199 NSOpenPanel-Klasse ...... 535 numberStyle-Eigenschaft ...... Init-Funktion ...... 268 Picker-View-Steuerelement ...... 1106, 1119 289 Datei auswählen ...... 1188 override-Schlüsselwort ...... Rollover ...... 1121 291 Verzeichnisauswahl ...... 1179 O Computed Properties ...... pickerView-Methode ...... 1121 740 Property Observers ...... 290 587 NSPasteBoard-Klasse ...... 311 364 picturesDirectory-Konstante ...... objc-Attribut ...... , 414 NSPasteboard.PasteboardType-Struktur ...... 732 View-Controller ...... Pipe-Klasse ...... 369 ObjCBool-Typ ...... 591 NSPhotoLibraryUsageDescription-Key ...... 781, 788 Pixel versus Punkt ...... 417 Object-relational Mapping (ORM) ...... 1017 NSPoint-Klasse ...... 735 P Platformspezifischer Code ...... 116 objectForKey-Methode ...... 1111 NSPoint-Struktur ...... 719 play-Methode ...... 759 objectValueForTableColumn-Methode ...... 652 Package Manager ...... 363, 993 NSPredicate-Klasse ...... 900, 901 playCommand-Eigenschaft ...... 766 Objektorientierte Programmierung ...... 241 Palindromtest ...... 187 929 787 NSProgressIndicator-Steuerelement ...... Observer (Eigenschaften) ...... 257 Parallax-Effekt ...... 941 playerViewDidBecomeReady-Methode ...... 735 22 NSRect-Klasse ...... Observer (Notification Manager) ...... 1085 Parameter ...... 138 Playgrounds ...... 719 39 NSRect-Struktur ...... Öffentliche Datenbank (CloudKit) ...... 889 autoclosures ...... 157 auf dem iPad ...... 189 199 NSRegularExpression-Klasse ...... Oktale Zahlen ...... 166 benannte Parameter ...... 128 Locale-Einstellungen ...... 538 546 834 NSResponder-Klasse ...... , on-Eigenschaft ...... 710 benannte, in Init-Funktionen ...... 267 playSoundFileNamed-Methode (SpriteKit) ...... 535 577 NSSavePanel-Klasse ...... open-Methode ...... 621, 622 benannte, in Protokollen ...... 305 PLIST-Format ...... 735 NSSize-Klasse ...... open-Schlüsselwort ...... 247 Inout-Parameter ...... 142 PNG-Datei speichern 719 1252 NSSize-Struktur ...... Operatoren ...... 71 noescape ...... 162 NSBitmapImageRep ...... 659 902 1175 NSSortDescriptor-Klasse ...... , Assoziativität ...... 86 optionale Parameter ...... 144 CGImage ...... 529 860 NSSplitter-Klasse ...... eigener Exponential-Operator ...... 89 unbenannte Parameter ...... 139 Polygon (SpriteKit) ...... 1167 1253 NSSplitView-Steuerelement ...... eigener Operatoren für komplexe Zahlen ...... 87 variable Anzahl ...... 144 Polygon zeichnen ...... 1181 297 Delegation ...... eigener Vergleichsoperator ...... 88 von Terminal-Apps ...... 35 Polymorphie ...... 1168 493 NSSplitViewController-Klasse ...... eigener Vergleichsoperator für Vektoren ...... 276 zweinamige Parameter ...... 140 Popover-Segue ...... 1181 474 NSSplitViewDelegate-Protokoll ...... Operatoren für CGPoint und CGVector ...... 174 Parsen popToRootViewController-Methode ...... 553 474 NSStatusBar-Klasse ...... Priorität ...... 86 Datum und Uhrzeit ...... 204 popToViewController-Methode ...... 179 493 NSString-Datentyp ...... selbst definieren ...... 87 Zahlen ...... 200 Popups ...... 753 1160 NSString-Klasse ...... selbst definieren (Beispiele) ...... 174, 198 PartialRangeThrough-Struktur ...... 80 5-Gewinnt-App ...... NSTableView-Steuerelement ...... 650 Optional Chaining ...... 85, 102 PartialRangeUpTo-Struktur ...... 80 Größe einstellen ...... 495 NSTableViewDataSource-Protokoll ...... 652 Optional Try ...... 343 Partikel-Emitter ...... 872 per Code anzeigen ...... 499 Icon-Resizer-Beispiel ...... 1182 optional-Schlüsselwort ...... 310 pasteConfiguration-Eigenschaft ...... 745 Richtung festlegen ...... 497 NSTableViewDelegate-Protokoll ...... 652, 1184 Optionale Funktionen/Methoden ...... 310 patch-Methode (Vapor) ...... 1008 popViewController-Methode ...... 474, 1099 NSTabViewController-Steuerelement ...... 526 Optionale Parameter ...... 144 path-Eigenschaft ...... 583 position-Eigenschaft ...... 810 NSTemporaryDirectory-Funktion ...... 588, 1190 Optionale Protokollregeln ...... 310 path-Methode (Bundle-Datei) ...... 584 post-Methode (Notification Manager) ...... 1085 NSTextField-Steuerelement ...... 512, 658 Optionals ...... 84, 99 pathFinder-Methode ...... 1243 post-Methode (Vapor) ...... 1008 NSUbiquitousKeyValueStore-Klasse ...... 883 als Rückgabewert von Funktionen ...... 130 Pattern-Zeichen ...... 72 postfix-Schlüsselwort ...... 88 NSURL-Klasse ...... 602 Codable-Protokoll ...... 619 pause-Methode ...... 769 Potenzieren ...... 74 NSURLConnection-Klasse ...... 605 doppelte Optionals ...... 343 pauseCommand-Eigenschaft ...... 766 pow-Funktion ...... 74 NSUUID-Klasse ...... 588 if-let-Kombination ...... 108, 740 PDF417-Barcode ...... 800 Precedence-Gruppen ...... 86 NSView-Klasse ...... 509, 657 in Kombination mit try ...... 343 Perfect-Framework ...... 986 precedence-Schlüsselwort ...... 88 NSViewController-Klasse ...... 509 Init-Funktion ...... 269 perform-Funktion ...... 925 precedencegroup-Schlüsselwort ...... 89

1294 1295

“buch” — 2017/10/6 — 8:49 — page 1296 — #1292 “buch” — 2017/10/6 — 8:49 — page 1297 — #1293

Index Index

preferredBarTintColor-Eigenschaft ...... 626 Properties ...... 254 rangeOfCharacter-Methode ...... 187 replaceCurrentItem-Methode ...... 768 preferredContentSize-Eigenschaft ...... 496 Computed Properties ...... 259, 291 rate-Eigenschaft ...... 770 replaceSubrange-Methode ...... 188, 214 preferredControlTintColor-Eigenschaft ...... 626 Extensions ...... 327 rawValue-Eigenschaft ...... 251 replacingOccurrences-Methode ...... 188, 659 preferredFocusEnvironments- Lazy Properties ...... 255 Enumerationen ...... 98 representedObject-Eigenschaft ...... 514 Eigenschaft ...... 571, 1261, 1277 Property Observers ...... 257, 290, 694, 1062, 1114 Read-Only-Eigenschaft ...... 261 Request-Klasse (Vapor) ...... 1009, 1011 prefersStatusBarHidden-Eigenschaft ...... 812, 1196 Property Observers (Beispiel) ...... 1153 readDataToEndOfFile-Methode ...... 369 requestAlwaysAuthorization-Methode ...... 672, 679 prefix-Methode ...... 218 Read-Only Computed Property ...... 261 readLine-Funktion ...... 147 requestRecordPermission-Methode ...... 773 prefix-Schlüsselwort ...... 88 Static Properties ...... 259 readObjects-Methode ...... 740 requestWhenInUseAuthorization-Methode ..... 672 prepare-Methode ...... 467, 522 Type Properties ...... 259 rear-Enumerationswert ...... 790 required-Schlüsselwort ...... 295 Detailansicht bei Table-View ...... 647 Property Lists Rear-Kamera ...... 795 reserveCapacity-Methode ...... 215 Fluent ...... 1018 propertyList-Methode ...... 740 Rechenoperatoren ...... 73 resignFirstResponder-Methode ...... 539 Popups auf dem iPhone ...... 495 PropertyListDecoder-Klasse ...... 614 Record speichern (CloudKit) ...... 898 Resistance Priority ...... 438 prepareToPlay-Methode ...... 759 PropertyListEncoder-Klasse ...... 614 Record Zones (CloudKit) ...... 891 resizeAspect-Konstante ...... 778 prepartions-Eigenschaft (Fluent) ...... 1024 User-Defaults ...... 577, 1061 record-Methode ...... 775 Resolve-Layout-Issues-Button ...... 418 preprareForDragOperation-Methode ...... 730 protocol-Schlüsselwort ...... 306, 334 recordID-Eigenschaft ...... 891, 899 ResourceRepresentable-Protokoll ...... 1022 present-Methode ...... 499, 504, 625 Protokolle ...... 304 recordName-Eigenschaft ...... 891, 899, 903 Responder für Alert-Dialoge ...... 504 erweitern ...... 328 Records und Record Types (CloudKit) ...... 890 Menüauswahl ...... 546 Presentation-Controller ...... 461 Extensions ...... 323 Redraw-Einstellung (contentMode) ...... 698 Responderkette ...... 544 presentedViewController-Eigenschaft ...... 417 für generische Typen ...... 312 reduce-Methode ...... 224 Tastaturereignisse ...... 538 Presenting Segues ...... 521 nur für Klassen ...... 307 mit inout-Parameter ...... 224 Response-Klasse (Vapor) ...... 1009 presentingViewController-Eigenschaft ...... 497 optionale Regeln ...... 310 Refactoring ...... 977 ResponseRepresentable-Protokoll (Vapor) ...... 1009 presentScene-Klasse ...... 868 Protocol Composition ...... 308 Reference Counting ...... 282 Ressourcen ...... 584 presses-Methoden ...... 565 Standardprotokolle ...... 314 ReferenceWritableKeyPath-Klasse ...... 333 REST-Konzept ...... 985 307 pressesBegan-Methode ...... 1260 Vererbung ...... Referenzen (CloudKit) ...... 899 restitution-Eigenschaft ...... 857, 1201 635 prettyPrinted-Konstante (JSONEncoder) ...... 615 Prototypzellen ...... Referenztypen ...... 72, 104 reStructuredText-Kommentare ...... 28 665 previousCommand-Eigenschaft ...... 766 Collection-View ...... Reflection ...... 332 Restwert-Operator ...... 73 400 956 previousLocation-Methode ...... 820 Provisioning Profile ...... , Regeln (Auto Layout) ...... 417 resume-Methode ...... 604 1038 previouslyFocusedItem-Eigenschaft ...... 571 Proxy-Konfiguration (Vapor) ...... register-Methode ...... 530, 631 rethrows-Schlüsselwort ...... 350 803 print-Funktion ...... 147 Pseudo-3D ...... registerForDraggedTypes-Methode 729, 732, 1178 Retroactive Modeling ...... 322 247 CustomStringConvertible-Protokoll ...... 314 public-Schlüsselwort ...... Reguläre Ausdrücke ...... 189 return-Schlüsselwort ...... 127 896 Printable-Protokoll ...... 314 publicCloudDatabase-Eigenschaft ...... Rekursion ...... 136 Reverse Polish Notation ...... 158 648 printf-Syntax ...... 197 Pull to Refresh (Table-View) ...... Enumerationen ...... 253 reverse-Methode ...... 215 417 Priorität von Operatoren ...... 86 Punkt versus Pixel ...... indirekte Enumeration ...... 253 reversed-Methode ...... 187 858 Privacy-Keys Pyramide (Beispiel) ...... Verzeichnisbaum durchlaufen ...... 592 SpriteKit-Aktionen ...... 836 Camera Usage ...... 783, 788 Relationen (Vapor/Fluent) ...... 1021 Richtung zwischen zwei Punkten ...... 1096 Location Usage ...... 673 Q reloadData-Methode ...... 647, 660, 755 Right-Shift (bitweises Rechnen) ...... 75 Microphone Usage ...... 773, 783 reloadRows-Methode ...... 647 rightMouseDown-Methode ...... 718 qos-Parameter ...... 922 Photo Library ...... 781, 788 reloadRowsAtIndexPaths-Methode ...... 1067 rightMouseDragged-Methode ...... 718 QR-Codes erkennen ...... 799 Private Datenbank (CloudKit) ...... 889 remove-Methode ...... 213, 230 rightMouseUp-Methode ...... 718 Quality of Service (async-Methode) ...... 922, 924 private set für Read-Only-Eigenschaften ...... 261 removeAllActions-Methode ...... 837 Rollover (Picker-View) ...... 1121 Query-Klasse (Vapor/Fluent) ...... 1021 private-Schlüsselwort ...... 247 removeFirst-Methode ...... 213 Root manifest not found (Vapor) ...... 1005 Queues (asynchrone Programmierung) ...... 923 privateCloudDatabase-Eigenschaft ...... 896 removeFromParent ...... 836 Root-View-Controller ...... 411, 416 Process-Klasse ...... 369 removeFromSubview-Methode ...... 1152 rootViewController-Eigenschaft ...... 411, 416, 488 ProcessInfo-Klasse ...... 559 R removeItem-Methode ...... 593 rotate-Methoden (SpriteKit-Aktionen) ...... 833 Production Environment (CloudKit) ...... 891 Rückgabewerte (Funktionen) ...... 129 removeItemAtPath-Methode ...... 1190 rotationRate-Eigenschaft ...... 828 Profil-Dateien (iOS/tvOS) ...... 982 Radio-Stream abspielen ...... 769 removeLast-Methode ...... 213 round-Funktion ...... 168 Programm radix-Parameter ...... 166 removeObserver-Methode ...... 1086 Routing (Vapor) ...... 1008 beenden (iOS) ...... 414 raise-Methode ...... 349 removeSubrange-Methode ...... 213 rowHeightForComponent-Parameter ...... 1123 beenden (macOS) ...... 517 RAM-Größe ermitteln ...... 559 Renju ...... 1127 RPN-Rechner ...... 158 signieren ...... 964 Rand eines Steuerelements ...... 413 repeat-Methode (SpriteKit-Aktionen) ...... 836 RSS-Datei auswerten ...... 662 weitergeben ...... 964 Random Numbers ...... 169 repeat-while-Schleife ...... 119 Ruby ...... 361 Projekte umbenennen ...... 978 range-Methode (Zeichenketten) ...... 188 repeatForever-Methode (SpriteKit) ...... 834, 836 run-Methode (SpriteKit) ...... 832, 837 prompt-Eigenschaft ...... 472 Range-Operatoren ...... 80 REPL-Modus ...... 37 runModal-Methode ...... 534, 535

1296 1297

“buch” — 2017/10/6 — 8:49 — page 1298 — #1294 “buch” — 2017/10/6 — 8:49 — page 1299 — #1295

Index Index

S self-Schlüsselwort ...... 246 showPhysics-Eigenschaft ...... 842 Split-View-Controller ...... 482, 1167, 1168 bei Enumerationen ...... 1130 showWindow-Methode ...... 525 Delegation ...... 1181 SafariServices-Bibliothek ...... 622 in Closures ...... 157 ...... 225 NYT-Beispiel ...... 1053 Safe Area Layout Guides ...... 420, 432 Shuffle-Algorithms in Mutating Methods ...... 274 ...... 276 433 Splitter-Steuerelement ...... 529 SpriteKit ...... 809 Signatur von Methoden , Klassentyp ...... 320 378 splitView-Methode ...... 1181 safeAreaLayoutGuide-Eigenschaft ... 434, 809, 1197 Simulator (iOS) ...... Self-Schlüsselwort ...... 246 675 splitViewController-Methode ...... 490 Sandbox GPS-Funktionen ...... Protokolle ...... 307, 316 259 SpriteKit ...... 803 iOS ...... 587 Singleton-Muster ...... Selfie-Kamera ...... 795 719 SQLite (Vapor) ...... 1025 macOS ...... 587 size-Eigenschaft ...... sequence-Methode (SpriteKit-Aktionen) ...... 836 815 sqlite.json-Datei (Vapor) ...... 1025 macOS, Icon-Resizer ...... 1170 SpriteKit ...... Sequence-Protokoll ...... 117 497 srand48-Funktion ...... 169, 1134 save-Methode sizeThatFits-Methode ...... Serielle Queues ...... 923 453 SSLHandshake failed (NSURL-Klasse) ...... 602 CloudKit ...... 898 sizeToFit-Methode ...... Server-APIs-Bibliothek ...... 992 832 Stack-Button ...... 418 Vapor/Fluent ...... 1021 SKAction-Klasse ...... Server-side Swift ...... 985 872 Stack-Speicher ...... 137 scale-Methoden (SpriteKit-Aktionen) ...... 833 SKEmitterNode-Klasse ...... sessionDidUpdate-Parameter ...... 747 818 Stack-View ...... 435 Scene-Editor ...... 865 SKLabelNode-Eigenschaft ...... Set-Datentyp ...... 230 842 Animationen ...... 709 SceneKit ...... 803 SKPhysicsBody-Klasse ...... Option-Sets ...... 231 845 rückgängig machen ...... 392 Schalter (UISwitch-Steuerelement) ...... 709 SKPhysicsContact-Klasse ...... uniqueSet-Methode ...... 330 841 1204 Standarddialoge ...... 533 Schatzsuche ...... 1075 SKPhysicsContactDelegate-Protokoll ...... , set-Methode (Key/Value-Speicher) ...... 883 841 iOS ...... 503 scheduledTimer-Methode ...... 925 SKPhysicsWorld-Klasse ...... set-Schlüsselwort ...... 96, 259, 279 842 Standardfunktionen ...... 145 Schlüssel-Wert-Paare ...... 226 visualisieren ...... setAction-Methode (NSColorPanel) ...... 537 standardOutput-Eigenschaft ...... 369 94 SKScene-Klasse ...... 808 Schlüsselwörter als Variablennamen ...... 314 setActive-Methode (AVAudioSession) ...... 773 868 Standardprotokolle ...... Schleifen ...... 117 in eine andere Szene wechseln ...... setCategory-Methode ...... 773 standardUserDefaults-Methode ...... 530 Scene-Editor ...... 865 abbrechen (break) ...... 119 827 setDataSouce-Methode ...... 656 816 startAccelerometerUpdates-Methode ...... nicht-triviale Schleifen ...... 121 SKShapeNode-Klasse ...... setDelegate-Methode ...... 656 Startansicht ...... 939 304 SKSpriteNode-Klasse ...... 810 Schnittstelle ...... 648 1063 827 setEditing-Methode ...... , 868 startDeviceMotionUpdates-Methode ...... Schrift auswählen ...... 533 SKTransition-Klasse ...... setFill-Methode ...... 691, 1086 startGyroUpdates-Methode ...... 827 532 SKU (Stock Keeping Unit) ...... 960 Schriftattribute ändern ...... 692 193 setLineDash-Methode ...... 847 startIndex-Eigenschaft ...... Schwerkraft (SpriteKit) ...... 841 SKView-Klasse ...... setNeedsDisplay-Methode ...... 694, 724, 733, 1148 startRunning-Methode ...... 794 Screenshots (Apple TV) ...... 557 sleep-Funktion ...... 926 setNeedsFocusUpdate-Methode ...... 571, 1277 starts-Methode ...... 219 scrollPosition-Parameter (Table-View) ...... 634 Slices (Arrays) ...... 212 setObject-Methode ...... 1111 startUpdatingHeading-Methode ...... 683 scrollToRow-Methode ...... 647, 1066 sort-Methode ...... 185, 214 CloudKit ...... 898 startUpdatingLocation-Methode ...... 679 scrollXxx-Methoden (NSEvent) ...... 540 für NSTableView ...... 659 setRegion-Methode ...... 680 state-Eigenschaft ...... 550, 1064, 1189 ...... 587 sortDescriptors-Eigenschaft ...... 659 SearchPathDirectory-Enumeration setSelectedFont-Methode ...... 536 Static Properties ...... 259 587 CloudKit ...... 902 SearchPathDomainMask-Struktur ...... setStroke-Methode ...... 691, 1086 static-Schlüsselwort ...... 275 780 sortDescriptorsDidChange-Parameter ...... 659 seek-Methode (AVPlayer) ...... setTarget-Methode (NSColorPanel) ...... 537 Statische Methoden ...... 275 460 sorted-Methode ...... 214 Segues ...... setTitle-Methode ...... 1063 Statusbar ...... 552, 812 522 sortedArray-Methode ...... 659 Datenübergabe ...... setVolume-Methode ...... 761 anzeigen ...... 438 465 Sortieren (CloudKit) ...... 902 Datenübertragung ...... SFSafariViewController-Klasse ...... 622 statusItem-Methode ...... 553 521 Sortierordnung für Zeichenketten ...... 186 macOS ...... Shapes (SpriteKit) ...... 816 Steuerelemente 469 ...... 973 per Code initiieren ...... Shared Init-Funktion ...... 296 Source Control ein- und ausblenden ...... 709 493 730 Popover ...... shared-Eigenschaft ...... 536, 537 sourceOperationMaskFor-Parameter ...... selbst programmieren ...... 687 462 467 Unwind ...... , shared-Methode ...... 416 sourceOperationMaskForDraggingContext- stop-Methode ...... 759 468 736 1185 verhindern ...... sharedApplication-Methode ...... 517, 1179 Parameter ...... , Stored Properties ...... 254 548 499 von Menüeinträgen ...... sharedWorkspace-Methode ...... 1179 sourceRect-Eigenschaft ...... Storyboard 479 781 784 788 790 Selected-Image-Eigenschaft ...... shift-Eigenschaft ...... 720 sourceType-Eigenschaft ...... , , , Fenster per Code erzeugen ...... 525 482 499 selectedIndex-Eigenschaft ...... Short-Circuit Evaluation ...... 80 sourceView-Eigenschaft ...... iOS ...... 375, 376 660 436 selectedRow-Eigenschaft ...... Shortest Path Algorithm ...... 1242 spacing-Eigenschaft ...... macOS ...... 519 482 967 selectedViewController-Eigenschaft ...... shouldAutorotate-Eigenschaft ...... 812 spctl-Kommando ...... storyboard-Eigenschaft ...... 525 1120 858 selectRow-Eigenschaft ...... shouldChangeCharactersInRange-Parameter 1117 speed-Eigenschaft ...... stride-Funktion ...... 125 634 559 selectRow-Methode ...... shouldPerformSegue-Methode ...... 468 Speicherplatz ermitteln ...... String-Datentyp ...... 179 282 selectXxx-Methoden (NSEvent) ...... 540 shouldUseExtendedBackgroundIdleMode- Speicherverwaltung ...... Interpolation ...... 181, 197 Selektor ...... 433, 553, 1063 Eigenschaft ...... 605 Spinner-Steuerelement ...... 920 als Datei lesen/schreiben ...... 595 Syntax ...... 277, 433 showDetailViewController-Methode ...... 489 split-Methode ...... 192, 224 Konstruktor ...... 166

1298 1299

“buch” — 2017/10/6 — 8:49 — page 1300 — #1296 “buch” — 2017/10/6 — 8:49 — page 1301 — #1297

Index Index

string-Methode Systemklänge abspielen ...... 768 Textured Button ...... 1168 Tupel ...... 233 DateFormatter ...... 203 systemSize-Konstante ...... 560 throws-Schlüsselwort ...... 346 als Rückgabewert von Funktionen ...... 130 NumberFormatter ...... 199 systemStatusBar-Methode ...... 553 bei Funktionsparametern ...... 350 in switch-Konstruktionen ...... 114 String.Index-Datentyp ...... 193 systemVersion-Eigenschaft ...... 559 Eigenschaften und Subscripts ...... 349 switch-Auswertung ...... 234 stringByAppendingPathComponent- Szene (iOS) ...... 376 in Init-Funktionen ...... 347 TVML-Apps ...... 555 Methode ...... 1190 Tilde-Operator (binäre Inversion) ...... 75 tvOS ...... 555 stringValue-Eigenschaft ...... 516, 658 T Tiled Textures ...... 815, 1210 Asteroids-Spiel ...... 1255 stroke-Methode ...... 691, 722, 733, 1086 Tiled-Programm ...... 1210 Bewegungssteuerung ...... 830, 1269 Tab-Bar-Controller ...... 476 strokeColor-Eigenschaft ...... 816 Tilemaps ...... 1210 Pac-Man ...... 1249 Tab-Bar-Items ...... 477 strong-Schlüsselwort ...... 283 Tileset ...... 1211 touch-Ereignisse ...... 823 Tab-View-Controller ...... 526 244 205 559 struct-Schlüsselwort ...... 481 timeIntervalSince-Methode ...... Versionsnummer ermitteln ...... tabBarController-Eigenschaft ...... 778 Strukturen ...... 242 Timer-Klasse ...... 925 Videos abspielen ...... Table-View-Steuerelement 249 94 verschachteln ...... 640 AVAudioRecorder-Beispiel ...... 776 Type Annotation ...... individuelle Zellengestaltung ...... 302 styleMask-Eigenschaft ...... 523, 524 Tint-Color (SFSafariViewController) ...... 626 Type Constraints ...... iOS ...... 629 287 259 Subclassing ...... 634 titleForRow-Parameter ...... 1122 Type Properties ...... Listeneintrag per Code auswählen ...... 333, 334 Subscriptions (CloudKit) ...... 891 650 TLSv1.2-SSL-Verschlüsselung für NSURL ...... 602 type-Funktion ...... macOS ...... 334 Subscripts ...... 278 635 To-do-Liste ...... 1060 Type-Schlüsselwort ...... Prototypzellen ...... 281 bequemer Zeichenkettenzugriff ...... 195 648 iCloud-Variante ...... 1070 typealias-Schlüsselwort ...... Pull to Refresh ...... 320 Fehler auslösen ...... 349 634 REST-API (Vapor) ...... 1013 AnyClass-Datentyp ...... Reaktion auf Elementauswahl ...... 304 Substring-Struktur ...... 195 1030 Generics ...... veränderliche Listen ...... 647 Token (Vapor-Authentifizierung) ...... 193 1169 Typen Substrings lesen Zellenhöhe einstellen ...... 644 Tool-Tipps ...... 167 995 Aliasse ...... 281 subtract-Methode ...... tableFooterView-Eigenschaft ...... 635 Toolbox (Vapor) ...... 167 432 Enumerationen ...... 250 subtracting-Methode ...... tableView-Methoden ...... 632, 652, 657, 753 Top Layout Guide ...... 1145 946 Klassen und Strukturen ...... 242 subviews-Eigenschaft ...... Icon-Resizer-Beispiel ...... 1182 Top Shelf Image (tvOS) ...... 188 488 Metatypen ...... 334 Suchen und Ersetzen in Zeichenketten ...... tableViewSelectionDidChange-Methode ...... 660 topViewController-Eigenschaft ...... 218 712 819 Referenz- und Werttypen ...... 104 suffix-Methode ...... Tag-Eigenschaft (Tab-Bar-Item) ...... 479 touches-Methoden ...... , 291 1268 Typmethoden ...... 275 super-Schlüsselwort ...... Tap Gesture Recognizer ...... 1118 Asteroids-Beispiel ...... 796 1202 supportedFlashModes-Eigenschaft ...... Targets (Xcode) ...... 1249 Breakout-Spiel ...... 812 862 supportedInterfaceOrientation-Eigenschaft .... Tastatur (iOS) ...... 379, 448 Kanonenkugel-Beispiel ...... U 147 1230 swap-Funktion ...... ausblenden ...... 452, 1118 Pac-Man-Beispiel ...... Ubuntu ...... 988 147 214 562 swapAt-Methode ...... , einblenden ...... 1069 tvOS ...... Uhrzeit ...... 203 1153 Swift Tastaturfokus setzen ...... 452, 1092 touchesBegan-Methode ...... UIActionController-Klasse ...... 1099 38 Compiler ...... Tastatur (macOS) ...... 538 touchesEnded-Methode ...... 1153 UIActivityIndicatorView-Steuerelement ...... 920 37 Interpreter ...... Teilzeichenketten extrahieren ...... 193 Trackpad ...... 718 UIAlertAction-Klasse ...... 504 993 Package Manager ...... Television Markup Language ...... 555 Trailer-Beispiel ...... 661 UIAlertController-Klasse ...... 503 39 Playgrounds für das iPad ...... Temporäre Datei ...... 588 Trailing Closures ...... 155 UIApplication-Eigenschaft ...... 416 116 Versionstest ...... Temporäres Verzeichnis ...... 588, 1190 Trailing-constraint-Warnung ...... 431 UIApplication-Klasse ...... 415, 622 146 176 swift-Schlüsselwort ...... , Inhalt löschen ...... 784 Traits (Auto Layout) ...... 440 UIApplicationDelegate-Protokoll ...... 415 360 swiftdoc-Dateien ...... terminate-Methode ...... 517, 1179 traits-Methode ...... 536 UIApplicationMain-Attribut ...... 365, 415 360 swiftmodule-Dateien ...... terminator-Parameter ...... 147 Transaktionen (CloudKit) ...... 891 UIBarButtonItem-Klasse ...... 472 Swipe Gesture Recognizer ...... 726 Ternärer Operator ...... 84 translatesAutoresizingMaskIntoConstraints- UIBarButtonItem-Steuerelement ...... 473 433 switch-Verzweigungen ...... 112 Beispiel ...... 710, 1148, 1158 Eigenschaft ...... UIBezierPath-Klasse ...... 860 Enumeration ...... 252 Terrains (in Tiled) ...... 1213 Transparenz ...... 708 Beispiel Kompass ...... 694 Tupel ...... 234 testable-Attribut ...... 248, 365 trashDirectory-Konstante ...... 587 Beispiel Richtungsanzeige ...... 1086 sync-Methode ...... 926 Testflight ...... 892 trashItem-Methode ...... 593 Grundlagen ...... 691 synchronize-Methode (iCloud) ...... 883 Textdateien ...... 595 trimmingCharacters-Methode ...... 186 UIButton-Steuerelement ...... 433 Syntaktischer Zucker Texteingaben (iOS) ...... 448 true ...... 170 UICollectionView-Steuerelement ...... 661 Generics ...... 301 textField-Methode ...... 451, 1117 truncatingRemainder-Methode ...... 1215 Beispiel zur Farbauswahl ...... 886 Optionals ...... 104 textFieldShouldReturn-Methode ...... 450 try-catch-Konstruktion ...... 337 UIColor-Klasse ...... 413 Synthesized Headers ...... 972 textLabel-Eigenschaft ...... 636 Forced Try ...... 343 Assets verwenden ...... 586 systemd-Service (Vapor) ...... 1039 Textur mit do-catch ...... 338 erweitern ...... 1132 systemFreeSize-Konstante ...... 560 Atlas ...... 833, 1209 ohne do-catch ...... 342 UIDevice-Klasse ...... 447, 559 Systemfunktionen aufrufen ...... 369 SpriteKit ...... 811 Optional Try ...... 343 UIDeviceOrientationDidChange-Konstante ...... 447

1300 1301

“buch” — 2017/10/6 — 8:49 — page 1302 — #1298 “buch” — 2017/10/6 — 8:49 — page 1303 — #1299

Index Index

UIDeviceOrientationDidChange-Nachricht ...... 699 UITabBarItem-Klasse ...... 477 UnsafeMutablePointer-Struktur ...... 367 Variablen ...... 93 UIDocument-Klasse ...... 877 UITableView-Steuerelement ...... 629 Unwind Segues ...... 462, 467 Variablennamen ...... 94 UIDocumentBrowserViewController-Klasse ..... 877 Delete on Swipe ...... 1067 Popups ...... 501 Variadics ...... 144 UIDragInteraction-Klasse ...... 745, 746 Drag & Drop ...... 749 Unwrapping-Operator ...... 85, 101 Vary for Traits ...... 444 UIDragInteractionDelegate-Protokoll ...... 743, 746 individuelle Zellengestaltung ...... 640 Upcast ...... 297 velocity-Eigenschaft ...... 857 UIDragItem-Klasse ...... 743, 746, 753 Prototypzellen ...... 635 updateFocusIfNeeded-Methode ...... 571, 1277 Veränderliche Parameter ...... 142 UIDragSession-Klasse ...... 743, 746 Pull to Refresh ...... 648 uppercased-Methode ...... 186 Vererbung ...... 287 UIDropInteraction-Klasse ...... 748 veränderliche Listen ...... 647 URL-Klasse ...... 601, 1108 bei Steuerelementen ...... 687 UIDropInteractionDelegate-Protokoll ...... 743 Zellenhöhe einstellen ...... 644 url-Methode (Bundle-Datei) ...... 585 eigene UIView-Klasse ...... 688 UIDropProposal-Klasse ...... 747, 748 UITableViewCell-Klasse ...... 631, 632, 642, 644 URL-Struktur ...... 582 Protokolle ...... 307 UIDropSession-Klasse ...... 748 UITableViewCellStyle-Enumeration ...... 636 URLForRessource-Methode ...... 530 Vergleichsoperatoren ...... 76 UIEdgeInsets-Klasse ...... 809 UITableViewController-Klasse ...... 630 URLRequest-Klasse ...... 622, 1052 Verschachtelte Funktionen ...... 135 535 UIFocusUpdateContext-Klasse ...... 571 UITableViewDataSource-Protokoll ...... 632 URLs-Eigenschaft ...... Versionsabhängiger Code ...... 115 587 UIFont-Klasse ...... 397 UITableViewDelegate-Protokoll ...... 634, 644 urls-Methode (FileManager) ...... Versionsnummer ermitteln (iOS/tvOS) ...... 559 606 UIGestureRecognizer-Klasse ...... 725 UITableViewDragDelegate-Protokoll ...... 753 urlSession-Delegate-Methoden ...... verticalAlignmentMode-Eigenschaft ...... 818 604 UIGestureRecognizerDelegate- UITableViewDropCoordinator-Protokoll ...... 754 URLSession-Klasse ...... Verzeichnisse 604 Protokoll ...... 1062, 1118 UITableViewDropDelegate-Protokoll ...... 753 URLSessionDownloadDelegate-Protokoll ...... auswählen ...... 533, 1179 604 UIGraphicsGetCurrentContext-Methode ...... 702 UITableViewDropProposal-Klasse ...... 753 URLSessionDownloadTask-Klasse ...... ermitteln ...... 586 199 UIGraphicsImageRenderer-Klasse ...... 705 UITapGestureRecognizer-Klasse ...... 1118 useGroupingSeparator-Eigenschaft ...... erzeugen ...... 1191 530 577 577 UIImage-Klasse ...... 639 UITextField-Steuerelement ...... 448 User-Defaults ...... , , Größe rekursiv ermitteln ...... 592 1274 Assets verwenden ...... 585 EditingChanged-Ereignis ...... 1118 Asteroids-Spiel ...... löschen ...... 1190 1061 Bild herunterladen ...... 602 ValueChanged-Ereignis ...... 1118 Beispiel ...... Inhalt auflisten ...... 589 530 UIImagePickerController-Klasse ...... 781, 788 UITextFieldDelegate-Protokoll ...... 450 Defaultwerte ...... temporäres Verzeichnis ...... 1190 577 UIImageView-Klasse UITextView-Steuerelement ...... 413 iOS ...... Verzeichnistest ...... 591 530 eigener Renderer-Code ...... 705 UITouch-Klasse ...... 712, 819, 1153 macOS ...... Verzweigungen ...... 107 1111 Instanz per Code erzeugen ...... 1122 UIView-Klasse ...... 408, 688, 1086 Währungsumrechner ...... videoGravity-Eigenschaft ...... 778 userAcceleration-Eigenschaft ...... 828 UIImageView-Steuerelement ...... 457, 642, 1104 Größenänderung feststellen ...... 1153 Videos userDirectory-Konstante ...... 587 UIKit-Framework ...... 409 Instanz per Code erzeugen ...... 1122 abspielen ...... 777 userDomainMask-Konstante ...... 587 UILabel-Klasse ...... 1122 UIViewController-Klasse ...... 408, 410 aufnehmen ...... 783 userInitiated-Enumerationswert ...... 922 mehrzeiliger Text ...... 453 Lebenszyklus ...... 410 auswählen ...... 781 usesGroupingSeparator-Eigenschaft ...... 1115 UILongPressGestureRecognizer-Klasse 1062, 1064 UIWebView-Steuerelement ...... 622 YouTube ...... 785 usesPreciseCollisionDetection-Eigenschaft ...... 857 UINavigationController-Klasse ...... 471 NYT-Bestseller-App ...... 1052 View utf16-Eigenschaft ...... 192 Beschriftung ändern ...... 474 UIWindow-Klasse ...... 407, 416 Größe fixieren ...... 523 UTF8 Navigation per Code ...... 474 Umrandung eines Steuerelements ...... 413 schließen (macOS) ...... 524 Textdateien ...... 595 UInt-Datentyp ...... 166 Unärer Operator ...... 84 View-Controller ...... 410, 508 Zeichenketten ...... 179 UIPasteConfiguration-Klasse ...... 745 Unable to simultaneously satisfy constraints Root-View-Controller ...... 411, 416 utf8-Eigenschaft ...... 192 UIPickerView-Steuerelement ...... 1106, 1119 (Fehlermeldung) ...... 433 view-Eigenschaft ...... 433, 553 utf8-Konstante ...... 201 Rollover ...... 1121 Unbenannte Parameter ...... 139 viewControllers-Eigenschaft ...... 481, 488 UUIDs erzeugen ...... 588 UIPickerViewDataSource-Protokoll ...... 1121 Unicode viewDidAppear-Methode ...... 411, 524 uuidString-Eigenschaft ...... 588 UIPickerViewDelegate-Protokoll ...... 1121 Skalar ...... 183 Animationen ...... 708 UIPopoverPresentationControllerDelegate- Textdateien ...... 595 macOS ...... 888 Protokoll ...... 495 unicodeScalars-Eigenschaft ...... 191 V viewDidDisappear-Methode ...... 411, 517, 1179 UIRefreshControl-Klasse ...... 649 Beispiel ...... 264 validateMenuItem-Methode ...... 550 viewDidLayoutSubviews-Methode ...... 411 UIScreen-Klasse ...... 408 Uniform Resource Locator ...... 582 values-Eigenschaft ...... 229 viewDidLoad-Methode ...... 413 UISplitViewController-Klasse ...... 482 uniqueKeysWithValues-Parameter ...... 227 Vapor-Framework ...... 986 Animationen ...... 708 NYT-Beispiel ...... 1053 uniqueSet-Methode ...... 330 Docker ...... 1003 macOS ...... 514 UISplitViewControllerDelegate-Protokoll ...... 490 uniquingKeys-Parameter (Dictionary) ...... 228 Hello World ...... 996 viewForTableColumn-Parameter ...... 657 UIStackView-Steuerelement ...... 418, 435 unlockFocus-Methode ...... 1173 Installation ...... 995 viewWillAppear-Methode ...... 411, 473 UIStoryboardSegue-Klasse ...... 467 unlockForConfiguration-Methode ...... 800 vapor-Kommando ...... 995 viewWillDisappear-Methode ...... 411, 473, 1097 UISwipeGestureRecognizer-Klasse ...... 726 unowned-Schlüsselwort ...... 283 var-Schlüsselwort ...... 93 viewWillLayoutSubviews-Methode ...... 411 UISwitch-Steuerelement ...... 709 unowned self in Closures ...... 161, 707 in switch-Konstruktionen ...... 114 Volltextsuche (CloudKit) ...... 901 UITabBarController-Klasse ...... 476 unrecognized-selector-Fehler ...... 386 mit if ...... 108 Volumes (Docker) ...... 990 UITabBarControllerDelegate-Protokoll ...... 481 unregisterDraggedTypes-Methode ...... 1178 mit while ...... 119 Volumes (SpriteKit) ...... 856

1302 1303

“buch” — 2017/10/6 — 8:49 — page 1304 — #1300

Index

W Projekte umbenennen ...... 978 Refactoring ...... 977 wait-Methode (SpriteKit-Aktionen) ...... 836 Verzeichnisse aufräumen ...... 979 WAV-Format ...... 759 XIB-Datei ...... 412 weak-Schlüsselwort ...... 283 XLIFF-Dateien ...... 951 Beispiel ...... 382, 522 XML-Bibliothek ...... 1107 Web-View ...... 622 XML-Daten verarbeiten ...... 610 Beispiel ...... 1052 XMLAttribute-Klasse ...... 610 NYT-Bestseller-App ...... 1052 XMLElement-Klasse ...... 610 WebKit-Bibliothek ...... 622 XMLIndexer-Klasse ...... 610 Webseiten anzeigen ...... 621 XMLParser-Klasse ...... 610 im Browser ...... 621 XWXMLHash-Bibliothek ...... 610 in der App ...... 622 Werttypen ...... 72, 104 where-Schlüsselwort Y Protokollerweiterungen ...... 329 y-Eigenschaft ...... 719 Regeln für generische Datentypen ...... 302 youtube-ios-player-helper-Bibliothek ...... 785 switch/case ...... 114 YouTube-Videos abspielen ...... 785 while-Schleife ...... 118 YTPlayerView-Klasse ...... 786 let (Optionals) ...... 119, 188 YTPlayerViewDelegate-Protokoll ...... 787 width-Eigenschaft ...... 719 Wildcard-Pattern-Zeichen ...... 72 Z Willkommensbildschirm ...... 939 166 willSet-Funktion ...... 257, 290 Zahlen ...... 179 Window-Controller ...... 508 Zeichenketten ...... 595 window-Eigenschaft ...... 416, 524, 553 als Datei lesen/schreiben 183 with-Funktion Copy-on-Write ...... 617 SpriteKit ...... 844 in Data-Element umwandeln ...... 184 UIBezierPath ...... 697 Länge ...... 185 withSize-Methode ...... 397 sortieren 195 WKWebView-Klasse ...... 622 Substrings bequemer lesen ...... 193 NYT-Beispiel ...... 1056 Substrings lesen ...... 193 write-Methode ...... 595, 1111 Teilzeichenketten extrahieren 185 write-Methode (Data-Struktur) ...... 1081 vergleichen ...... 369 writeToFile-Methode ...... 355 zeilenweise zerlegen ...... 203 Wuziqi ...... 1127 Zeit ...... messen ...... 205 206 X vergleichen ...... Zeit formatieren ...... 776 719 x-Eigenschaft ...... Zellenhöhe einstellen (Table-View) ...... 644 455 584 Xcassets-Datei ...... , zero-Eigenschaft ...... 173 813 Spritekit ...... zip-Funktion ...... 148, 227 639 UIImage-Objekt erzeugen ...... Zip2Sequenz-Datentyp ...... 148 899 URL von Bild erzeugen ...... Zonen (CloudKit) ...... 891 22 Xcode ...... zPosition-Eigenschaft ...... 811 971 Arbeitstechniken ...... zRotation-Eigenschaft ...... 815 67 Code-Konverter ...... Zufallszahlen ...... 169 58 Crashkurs ...... Zugriffsebenen ...... 246 976 Crashlogs ...... Zuweisung ...... 72 31 erste Schritte ...... Zweidimensionale Arrays ...... 1132 1002 für Server-Projekte ...... Zweinamige Parameter ...... 140 Git ...... 973 Hello iOS-World ...... 374 Literale ...... 811 mehrsprachige Apps ...... 947

1304

Wissen,Wissen, wie’s wie’s geht. geht.

Michael Kofler hat Telematik an der TU Graz studiert. Er zählt zu den erfolgreichsten und vielseitigsten Com- puterbuchautoren im deutschen Sprachraum. Zu sei- nen Themengebieten zählen neben Java auch Linux, OS X, der Raspberry Pi, MySQL, KVM, Visual Basic und Excel-VBA. Viele seiner Bücher wurden übersetzt. Michael Kofler arbeitet auch als Software-Entwickler, Berater sowie als Lehrbeauftragter an zwei Fachhoch- schulen.

Wir hoffen sehr, dass Ihnen diese Leseprobe gefallen hat. Gerne dürfen Sie diese Leseprobe empfehlen und weitergeben, aller- dings nur vollständig mit allen Seiten. Die vorliegende Leseprobe ist in all ihren Teilen urheberrechtlich geschützt. Alle Nutzungs- Michael Kofler und Verwertungsrechte liegen beim Autor und Verlag. Swift 4 – Das umfassende Handbuch 1.304 Seiten, gebunden, Oktober 2017 49,90 Euro, ISBN 978-3-8362-5920-0 Teilen Sie Ihre Leseerfahrung mit uns!

www.rheinwerk-verlag.de/4494