Swift 3.1

Mit Xcode 8.3/Swift 3.1 hat Apple ein Mini-Release herausgebracht. Swift 3.1 ist zu 99,99% kompatibel zu Swift 3.0, hat aber ein paar kleine neue Features dazubekommen. Richtig Bewegung in die Swift-Entwicklung wird erst im Herbst kommen, wenn Swift 4.0 fertig wird. (Daran wird hinter den Kulissen schon eifrig gearbeitet, aber in Swift 3.1 ist das noch nicht zu sehen.)

Eines gleich vorweg: Ich habe alle Beispieldateien zu meinem Swift-3-Buch mit Xcode 8.3 getestet — immerhin rund 60 Playgrounds und rund 100 Projekte. Das Ergebnis: ganze 7 Warnings. Einmal beklagte der Swift-Compiler, dass M_PI deprecated ist und ich lieber Double.pi verwenden sollte. Die anderen sechs Mal ging es um die Ausgabe von Optionals durch print in der Form print("bla = \(var)"). In diesen Fällen lautet die Warnung: String Operation for Optional Value produces debug description for optional value. Abhilfe schafft die Angabe eines Defaultwerts (also var ?? "--") oder ein vorgestelltes if let, das sicherstellt, dass das Optional wirklich Daten enthält.

Was die Kompatibilität betrifft, hat Apple also diesmal wirklich ganze Arbeit geleistet. Anders als Swift 2.2 vor einem Jahr bleibt den Entwicklern Kompatibilitätsärger zwischendurch erspart. Super!

Ein paar kleine Neuerungen, die keine Kompatibilitätsprobleme verursachen, hat Apple aber doch in Swift 3.1 eingebaut.

Sequences

Sequences können nun mit prefix(while:) bzw. drop(while:) verarbeitet werden. prefix testet die ersten Elemente der Sequenz und liefert alle zurück, bis die while-Bedingung zum ersten Mal nicht zutrifft. Der Rest der Sequenz wird nicht mehr bearbeitet.

drop agiert umgekehrt und verwirft solange Elemente vom Beginn der Sequenz, bis die while-Bedingung zum ersten Mal nicht mehr erfüllt ist. Der Rest der Sequenz wird zurückgegeben.

let lst = [1, 2, 3, 4, 1, 2, 3, 4]
let result1 = lst.prefix(while: {$0 < 3})
result1  // [1, 2]

let result2 = lst.drop(while: {$0 < 3})
result2  // [3, 4, 1, 2, 3, 4]

Failable numeric initializers

Die Datentypen Int, Int8, etc., Float, Float80 und Double haben neue Init-Funktionen in der Form init?(exactly:) erhalten. Wenn eine Konversion möglich ist, liefern sie die gewünschte Zahl, sonst nil.

let i = 1234
if let ui = UInt8(exactly: i) {
  print(i)
} else {
  print("UInt8 hat nil zurückgegeben.")
  // das ist bei diesem Beispiel der Fall
}

Extensions mit Typ-Constraints

Extensions können nun so formuliert werden, dass sie nur für bestimmte Datentypen gelten.

// Array erweitern, aber nur für Int-Arrays
extension Array where Element == Int {
  func sum() -> Int {
    return self.reduce(0) { $0 + $1 }
  }
}
let data = [1, 2, 3, 4]
data.sum()  // Ergebnis 10

Verschachtelte Generics

Swift 3.1 erlaubt verschachtelte Typen mit generischen Parameter innerhalb von generischen Typen. Die Release Notes fassen die neuen Syntaxmöglichkeiten gut zusammen:

struct OuterNonGeneric {
       struct InnerGeneric<T> {}
}
struct OuterGeneric<T> {
       struct InnerNonGeneric {}
       struct InnerGeneric<T> {}
}
extension OuterNonGeneric.InnerGeneric {}
extension OuterGeneric.InnerNonGeneric {}
extension OuterGeneric.InnerGeneric {}

Quellen