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
- https://www.raywenderlich.com/156352/whats-new-in-swift-3-1
- https://www.hackingwithswift.com/swift3-1
- https://bugs.swift.org/browse/SR-1009 (Extensions with Type Constraints)
- https://twitter.com/lorentey/status/846501171284115456 (schönes Beispiel für Extensions with Type Constraints)
- https://bugs.swift.org/browse/SR-1446 (Nested Generics)
- https://developer.apple.com/library/content/releasenotes/DeveloperTools/RN-Xcode/Chapters/Introduction.html