Swift 1.2

Seit gut einer Woche ist Xcode 6.3 mit Swift 1.2 verfügbar. Das ist das zweite »Minor Update« der Programmiersprache Swift. Lesen Sie hier, was sich im Vergleich zur Version 1.1 (Xcode 6.2) geändert hat.

Syntax

  • Casting 1: Casts, die Fehler auslösen können, müssen nun mit as! formuliert werden. Das ist eine inkompatible Änderung zu Swift 1.0 und erfordert Änderungen im Code! Auch viele Swift-Beispiele im Internet laufen aufgrund dieser Änderung nicht mehr. (Xcode enthält das Kommando Edit / Convert / To Swift 1.2, um alten Swift-Code anzupassen.)
    if obj is UInt32 {
      var ui32 = obj as! UInt32
    }
    
  • Casting 2: Es gibt keine implizite Umwandlung von Objective-C-Typen wie NSString, NSArray oder NSDictionary in die entsprechenden Swift-Typen mehr. Vielmehr muss die Konversion nun durch as String oder as Array explizit ausgedrückt werden. Hier ist kein as! erforderlich, weil keine Gefahr besteht, dass die Umwandlung scheitert.
    let ns = NSString(format: "%04d", 12)  // NSString-Instanz
    let s:String = ns as String            // Swift-String
    // bisher funktionierte auch:
    // let s:String = ns 
    
  • let: Wenn der Swift-Compiler erkennen kann, dass von verschiedenen Code-Zweigen immer nur einer ausgeführt werden kann, dann sind nun auch mehrere unterschiedliche Zuweisungen für eine Konstante erlaubt:
    let c:String  // in c soll eine Farbe gespeichert werden
    if arc4random() % 2 == 0 {
      c = "Red"
    } else {
      c = "Green"
    }
    
  • if-let: if-let-Konstruktionen können nun mehrere Optional-Zuweisungen auf einmal durchführen und die Zuweisung mit Bedingungen verknüpfen. Das vermeidet zumindest in manchen Fällen endlos verschachtelte if-let-Ketten. Die folgenden Zeilen zeigen dazu ein konkretes Beispiel aus einer iOS-App.
    let pfd =         // pfd hat den Datentyp [AnyObject]!
      NSSearchPathForDirectoriesInDomains(
        .DocumentDirectory, .UserDomainMask, true)
    if pfd != nil && pfd.count>0, let path = pfd[0] as? String {
      println(path)   // path hat den Datentyp String
    }
    

Neue/geänderte Datenstrukturen

Neben Arrays und Dictionaries gibt es nun auch Sets. Ein Set ist eine ungeordnete Menge einmaliger Elemente (keine Doppelgänger). Beim Datenaustausch mit Objective-C-Code wird das neue Set in NSSet umgewandelt (bridging).

var set = Set<Int>()        // leeres Set erzeugen
do {                        // Lottozahlen einfügen
  set.insert(Int(arc4random_uniform(49))+1)
} while(set.count<6)        // sechs Zahlen ohne Doppelgänger

var lotto = Array(set)      // in Array umwandeln
lotto.sort(<)               // und sortieren
println(lotto)              

Einige weniger bekannte Swift-Datentypen haben neue Namen bekommen bzw. sind jetzt anders implementiert:

  • Slice -> ArraySlice
  • HeapBuffer, HeapBufferStorage, OnHeap -> ManagedBuffer, ManagedBufferPointer, ManagedProtoBuffer

Neue Standardfunktionen

Zu map existiert die neue Variante flatMap. Sie eignet sich vor allem dann, wenn eine map-Funktion selbst Arrays erzeugt. Das führt dann zu verschachtelte Arrays. flatMap bildet aus den Ergebniselementen hingegen ein einziges, eindimensionales Array:

var ar = [1, 2, 3]
let nested = map(ar, { Array(1...$0) })
// nested = [[1], [1, 2], [1, 2, 3]]
let flat = flatMap(ar, { Array(1...$0) })
// flat = [1, 1, 2, 1, 2, 3]

Die neue Funktion zip verknüpft die Elemente aus zwei Sequenzen paarweise verknüpft. Das Ergebnis ist eine Instanz des Zip2-Datentyps. Wenn die beiden Sequenzen unterschiedlich viele Elemente aufweisen, dann bestimmt die kürzere Sequenz die Anzahl der Ergebnis-Tupel.

// Messzeiten und Messwerte in zwei Arrays
let time =  ["12:15", "12:30", "12:45", "13:00"]
let temp = [20.9, 20.8, 20.7, 20.9]
let combined = zip(time, temp)  // Zip2<[String], [Double]>

zip erzeugt also eine neue Datenstruktur mit zweiteiligen Tupel, die Sie nun mit den anderen Funktionen verarbeiten können:

map(combined, { println("Zeit: ($0) Temperatur: ($1)°") } )
// Ausgabe: Zeit: 12:15 Temperatur: 20.9°
//          Zeit: 12:30 Temperatur: 20.8°
//          Zeit: 12:45 Temperatur: 20.7°
//          Zeit: 13:00 Temperatur: 20.9°

Zu guter Letzt: Aus countElements wurde einfach count. Sehr vernünftig!

Swift und Objective C

Die Kompatibilität zwischen Swift und Objective C wurde in diversen Details verbessert.

  • Mit dem Attribut @objc gekennzeichnete Swift-enums sind nun portabel zu Objective-C-Code.
  • In Objective-C-Code können durch zusätzliche Type Qualifier genauer beschrieben werden.
    • nonnull bzw. __nonnull: nicht optionale Daten, entspricht in Swift z.B. let varname:Type
    • nullable bzw. __nullable: optionale Daten, entspricht in Swift z.B. let varname:Type?
    • null_unspecified bzw. __nul_unspecified: *implicitly unwrapped optionals, entspricht in Swift z.B.let varname:Type!`

    Diese Änderung verspricht längerfristig eine bessere Adaption der Apple-Frameworks für Swift.

Der Playground, jetzt noch verspielter

Der Playground ist in erster Linie eine interaktive Testumgebung, um Swift auszuprobieren. Die wesentliche Neuerung in Xcode 6.3 / Swift 1.2 besteht darin, dass nun auch Markdown-formatierte Kommentare erlaubt sind. Das ermöglicht die Gestaltung optisch ansprechender Playground-Dokumente.

Markdown-formatierte Kommentare im Playground
Markdown-formatierte Kommentare im Playground

Genaugenommen unterstützt Swift ist ein Subset der reStructuredText-Syntax. Eine Referenz der erlaubten Syntaxelemente finden Sie in der Apple-Playground-Dokumentation. Formatierte Kommentare sind natürlich auch in richtigen Swift-Projekten erlaubt. Sie werden mit /// bzw. mit /** eingeleitet.

Die Box zeigt Kontextinformationen zu einer Methode, die mit Markdown-Kommentaren dokumentiert ist.
Die Box zeigt Kontextinformationen zu einer Methode, die mit Markdown-Kommentaren dokumentiert ist.

Compiler

Der Swift-Compiler wurde wesentlich schneller. Besonders spürbar sind die Optimierungen bei großen Projekten, in denen der Compiler nun nur noch Code kompiliert, der wirklich verändert wurde (incremental builds).

Dass auch die Performance des kompilierten Codes deutlich zugenommen hat, habe ich ja schon hier beschrieben.

Quellen