30. Januar 2019

Einführung in Swift

Überblick Programmiersprachen Swift & Objective-C

Apple hat 2014 hat auf der jährlichen Entwicklerkonferenz WWDC die Programmiersprache Swift vorgestellt. Seitdem wurde diese Sprache umfangreich erweitert und verbessert. Nachdem die ersten Versionen von Instabilitäten und mit den Vorgängerversionen inkompatiblen Sprachänderungen geprägt waren, hat sich die Entwicklung der Sprache seitdem stabilisiert. Mit Xcode 10 wurde im September 2018 Version 4.2 von Swift ausgeliefert. Diese Version ist bis auf Details rückwärtskompatibel und es wurden nur minimale Änderungen an bestehendem Code notwendig.

Swift ist eine moderne, objektorientierte Programmiersprache, die viele Ideen aus anderen Paradigmen wie der funktionalen Programmierung und aus Programmiersprachen wie Objective-C, Rust, Haskell, Ruby und Python aufgreift. Obwohl Swift eine typsichere, compilierte Sprache ist, für die der Compiler viele Fehler bereits in der Compilierphase erkennen kann, hat sie eine sehr elegante und kompakte Syntax, die an Skriptsprachen erinnert. Beispielweise können Typdeklarationen in Swift-Code häufig entfallen, da der Swift-Compiler die Typen automatisch ermittelt:

let names = ["Bob", "Alice"]    // Compiler ermittelt den Typ Array<String> für names
for name in names {             // Compiler ermittelt den Typ String für name
   print("Hello \(name)!")
}

Im Gegensatz zu Swift ist Objective-C, das vor Swift zur Programmierung von iOS-Apps verwendet wurde, eine Erweiterung der C-Programmiersprache. Es erweitert C um Sprachkonstrukte zur objektorientierten Programmierung. Die Syntax von Objective-C wurde stark von der Sprache Smalltalk inspiriert und hat daher eine ungewöhnliche Syntax - zum Beispiel werden Methodenaufrufe in eckigen Klammern geschrieben:

NSString *str = @"Hello world";
NSString *hello = [str substringToIndex:5];

Apple hat mehrfach deutlich gemacht, das Objective-C neben der neuen Programmiersprache Swift weiterhin vollwertig unterstützt wird. Es wurde auf die Kompatibilität zwischen den beiden Sprachen geachtet - so können Objective-C Klassen aus Swift heraus verwendet werden und umgekehrt. Dies funktioniert mit einigen Einschränkungen gut - schwierig wird es, wenn neue Swift-Sprachfeatures zum Einsatz kommen, zu denen es in Objective-C keine Entsprechung gibt.

Aufgrund seineren einfacheren und moderneren Syntax ist Swift der klare Favorit für die Entwicklung von Apps. Objective-C kommt hauptsächlich in bestehenden Projekten zum Einsatz, die bereits in Objective-C entwickelt wurden oder in Projekten, in denen die Notwendigkeit besteht, tiefgreifend mit bestehendem C/C++-Code zu interagieren.

Allgemeines zur Syntax von Swift

Das Semikolon am Zeilenende ist in Swift optional und kann entfallen:

print("Hello World")
print("Hello World");
print("Hello"); print("World")

Kommentare können zeilenweise oder blockweise verwendet werden. Praktischerweise bereiten Kommentarzeichen in Kommentaren keine Probleme:

// Kommentierte Code-Zeile
/* Kommentierter
     Code-Block */
/* Das ist kein Problem in Swift: /* print("Hello World") */   */

In Xcode können Sie mit Editor » Structure » Toggle Comments ⌘/ den ausgewählten Code-Block kommentieren bzw. den Kommentar wieder entfernen.

Deklaration von Variablen und Konstanten

Swift unterscheidet die Deklaration von Variablen mit var:

var stringVariable = "Hello Swift!"

und Konstanten mittels let:

let stringConstant = "Hello Swift!"

Mit let deklarierte Konstanten dürfen nach der initialen Zuweisung nicht mehr verändert werden:

Compilerfehler: Erneute Zuweisung einer mit let deklarierter Konstante

Typinferenz und explizite Typdeklaration

In Swift können Typdeklarationen entfallen sofern der Compiler den Typ ermitteln kann. So kann in der folgenden Deklaration die Typangabe weggelassen werden, da sich der Typ aus dem zugewiesenen Wert ergibt:

var str = "Hello world!"

Optional kann der Typ folgendermaßen explizit deklariert werden - folgende Deklaration ist mit der vorhergehenden gleichwertig:

var str: String = "Hello world!"

Primitive Datentypen

Swift stellt Datentypen für vorzeichenlose und vorzeichenbehaftete ganzzahlige Werte, für Fließkommazahlen und boolesche Werte bereit:

var numberInt8   : Int8     //                       -128 -                       127
var numberInt16  : Int16    //                    -32.768 -                    32.767
var numberInt32  : Int32    //             -2.147.483.648 -             2.147.483.647
var numberInt64  : Int64    // -9.223.372.036.854.775.808 - 9.223.372.036.854.775.807

var numberUInt8  : UInt8    //                          0 -                        255
var numberUInt16 : UInt16   //                          0 -                     65.535
var numberUInt32 : UInt32   //                          0 -              4.294.967.295
var numberUInt64 : UInt64   //                          0 - 18.446.744.073.709.551.615

var numberInt    : Int      // plattformabhängig Int32 bzw. Int64
var numberUInt   : UInt     // plattformabhängig UInt32 bzw. UInt64

var numberFloat  : Float    // 32-bit Fließkommazahl
var numberDouble : Double   // 64-bit Fließkommazahl

var booleanValue : Bool = true

Funktionen und Parameter

Mit func werden Funktionen definiert. Parameter werden benannt:

func greeting(name: String) -> String {
    let greeting = "Hallo \(name)!"
    print(greeting)
    return greeting
}

print(greeting(name: "Bob"))

Die Parameter müssen beim Aufruf der Funktion in der vorgegebenen Reihenfolge übergeben werden und Swift unterscheidet zwischen dem Parameter-Namen und dem Argument Label:

func myFunction(argumentLabel parameterName: Int) {
    print(parameterName)
}

func greet(name: String, from city: String) {
    print("Hallo \(name) aus \(city)!")
}

myFunction(argumentLabel: 5)
greet(name: "Bob", from: "München")

Mit _ als Argument Label kann ein namenloser Parameter definiert werden:

func greet(_ name: String) {
    print("Hallo \(name)!")
}

greet("Bob")

Datenstrukturen: Listen

In Swift können Listen mit dem Array-Literal [...] erstellt werden:

var words = ["bird", "tree", "house"]
let numbers = [1, 2, 3]

Es handelt sich dabei um eine veränderliche Liste, sofern die Deklaration mit var erfolgt. Der Listentyp macht Gebrauch von dem generischen Typsystem von Swift. Im Beispiel wird der Compiler z.B. für words automatisch den Typ Array<String> ermitteln, der abgekürzt als [String] geschrieben werden könnte:

var words: [String] = ["bird", "tree", "house"]

Das heißt, bei der Verwendung von Listen ermittelt und prüft der Compiler die Typen der Listenelemente. So werden in folgendem Beispiel die Konstanten vom Compiler automatisch als String deklariert:

let firstWord = words.first
let secondWord = words[1]
let lastWord = words.last

Initialisierung, Eigenschaften und Methoden

Werte werden in Swift mit dem Aufruf „Typname(...)“ initialisiert. In dem folgendem Beispiel werden Arrays explizit über den Initializer des Array-Typs erzeugt:

var emptyArray = [String]()
var array = Array(repeating: "A", count: 3) // ["A", "A", "A"]

Klassen können Eigenschaften (Properties) deklarieren, die gelesen und je nach Deklaration gesetzt werden können, zum Beispiel:

let count = array.count

Einige gängige Methoden bei der Verwendung des Arrays sind:

let str = array.joined(separator: ",")

array.insert("B", at: 0)
array.append("C")

Zeichenketten

Swift stellt für Zeichenketten den Typ String bereit. In Swift können in Zeichenketten mittels der String-Interpolation-Syntax \(...) Werte eingesetzt bzw. Ausdrücke evaluiert werden:

let words = ["bird", "tree", "house"]
let formattedString = "Results: \(words.count) words in \(words)"

Ausgaben auf der Konsole

Mit der Funktion NSLog wird eine Zeichenkette anhand eines Format-Strings formatiert und auf der Konsole ausgegeben. Dabei werden %-Platzhalter durch die übergebenen Werte ersetzt:

NSLog("Results: %i words in %@", wordCount, words)

Da hier die Reihenfolge der Parameter genau der Reihenfolge der Platzhalter im Format-String entsprechen muss, empfiehlt es sich, auch hier mit der modernen Swift-Syntax zu arbeiten. Zu beachten ist jedoch, dass das 1. Argument weiterhin ein Format-String ist:

NSLog("%@", "Results: \(wordCount) words in \(words)")    

Xcode: Playgrounds

Mit File » New » Playground können Sie in Xcode einen Playground erstellen, in dem Swift-Code unmittelbar compiliert und ausgeführt wird:

Xcode Playground

Xcode: Code-Vervollständigung

An vielen Stellen kann Code in Xcode mit ^+Space vervollständigt werden:

Xcode Code-Vervollständigung

Nach Verwendung der Vervollständigung kann mit Tab zwischen den Parameterwerten gewechselt werden:

Xcode Code-Vervollständigung - Parameterwechsel mit Tab

Xcode: Dokumentation

Mit einem Klick mit gedrückter -Taste auf einen Bezeichner oder einem Force-Touch auf dem Touchpad wird die Dokumentation angezeigt:

Xcode Dokumentation anzeigen

Unter Reference finden Sie die vollständige Dokumentation der jeweiligen Klasse. Im Inhaltsverzeichnis finden Sie die Liste aller Methoden, mit ⌘F suchen Sie in der Dokumentation:

Xcode Dokumentation: String-Methoden

Tutorial 1: Swift-Grundlagen im Playground

  1. Erstellen Sie zum Kennenlernen der Swift-Programmiersprache mit File » New » Playground... einen neuen Playground:

    Xcode » File » New » Playground

  2. Code, den Sie in einem Playground einfügen, wird von Xcode compiliert, ausgeführt und sie sehen die Ergebnisse in der rechten Spalte. Entfernen Sie den bestehenden Code (für dieses Tutorial beschränken wir uns auf die Verwendung der Swift-Standard-Bibliothek, die Oberflächenbibliothek UIKit muss daher nicht importiert werden). Tippen Sie testweise einen Ausdruck wie 1 + 1.

  3. Verwenden Sie die Option Automatically Run oder Manually Run + Play-Button im Zeilenlineal:

    Xcode Playground
  4. Deklarieren Sie eine String-Variable und Konstante mittels var und let:

    var str = "Hello, playground"
    let strConstant = "Hello world!"
  5. Lassen Sie sich per -Klick bzw. per Force-Touch auf dem Touchpad auf die str-Variable den vom Compiler ermittelten Typ anzeigen und rufen Sie die zugehörige Dokumentation auf:

    Xcode Dokumentation anzeigen
  6. Machen Sie sich mit der Xcode-Code-Vervollständigung vertraut. Tippen Sie „str.“ und lassen Sie mit Ctrl + Space eine Liste aller Methoden und Eigenschaften des Objektes anzeigen:

    Xcode Code-Vervollständigung

  7. Wählen Sie die Methode lowercased():

    str.lowercased()
  8. Finden Sie über Help » Documentation and API Reference ⇧⌘0 die Eigenschaft, um zu prüfen, ob eine Zeichenkette leer ist:

    Xcode Documentation and API Reference
  9. Verwenden Sie die Eigenschaft im Playground und lassen Sie die Länge der Zeichenkette mit str.count ausgeben.

  10. Machen Sie sich weiter mit der Deklaration von Variablen mit var und Konstanten mit let vertraut, indem Sie einige Deklarationen schreiben und dabei die Typen String, Int, Float, Bool verwenden. Verwenden Sie sowohl eine explizite Typdeklaration als auch eine vom Compiler ermittelte Typdeklaration, beispielsweise:

    let number1: Int = 5
    let number2 = 5
    let floatNumber = 1.0
    let boolValue = true
  11. Deklarieren Sie eine Liste von Wörtern und iterieren Sie die Liste mit einer for-Schleife. Geben Sie jedes Wort mit print auf der Standardausgabe aus:

    let words = ["bird", "tree", "house"]
    for word in words {
        print("* ", word)
    }
  12. Blenden Sie zur Prüfung des Ergebnisses die Debug Area ein:

    Playground Debug Area
  13. Ermitteln Sie die Länge der Liste und geben Sie das erste und zweite Element aus:

    list.count
    list.first
    list[1]
  14. Deklarieren Sie eine leere Liste - hier wird eine explizite Typangabe benötigt, da der Swift-Compiler den Wertetyp nicht anhand gegebener Listenelemente ermitteln kann:

    let emptyList : [String] = []
  15. Machen Sie sich anhand des folgenden Code-Beispiels mit der Syntax zur Erstellung von Objekten und dem Aufruf von Methoden und der Code-Vervollständigung in Xcode vertraut:

    var array = Array(repeating: "A", count: 3)
    array.removeLast()
    array.append("B")
    array.insert("C", at: 0)
    array.joined(separator: ",")

    Machen Sie sich dabei weiter mit der Xcode-Code-Vervollständigung vertraut: Mit Ctrl-Space können Sie die Vervollständigung manuell auslösen, mit Escape abbrechen, mit Enter wird der Vorschlag übernommen und mit Tab kann danach zwischen den Parametern gewechselt werden:

    Xcode Code-Vervollständigung