Voraussichtlich ist Swift 2.2 die letzte Swift-Version vor dem großen, für Herbst geplanten Update auf Swift 3. Swift 2.2 bietet im Vergleich zu Swift 2.0/2.1 einige neue Funktionen. Beim Design von Swift 2.2 war die Kompatibilität zu vorhandenem Swift-2-Code ein wichtiges Ziel. Die meisten Neuerungen sind als Ergänzungen/Erweiterungen konzipiert, die optional verwendet werden können, aber keinen Einfluss auf vorhandenen Code haben.
Dennoch zeigt Swift 2.2 bereits in einigen Punkten die Richtung an, in die sich Swift weiterentwickelt. So wurden diverse Sprachmerkmale von Swift als deprecated gekennzeichnet. Das betrifft z.B. klassische for
-Schleifen, die in Swift 2.2 weiter ausgeführt werden, in Xcode aber als deprecated gekennzeichnet werden. Diese Kennzeichnung gibt Entwicklern die Möglichkeit, schon jetzt damit zu beginnen, ihren Code möglichst Swift-3-konform zu gestalten.
Diese Artikel fasst die Neuerungen auf der Basis von Xcode 7.3 Beta 5 zusammen. Ich werde den Text nach der Freigabe von Xcode 7.3 nochmals aktualisieren. Inzwischen ist Xcode 7.3 freigegeben. Es hat keine für diesen Artikel relevanten Änderungen mehr gegeben.
Lesen Sie auch die Zusammenfassung über den aktuellen Stand der Pläne für Swift 3!
Neu: Tupel-Vergleiche
Bis einschließlich Swift 2.1 können Tupel nicht verglichen werden. Swift 2.2 stellt für Tupel mit bis zu sechs Elementen die Operationen ==
und !=
zur Verfügung.
//: Tupel vergleichen (zulässig für Tupel mit bis zu sechs Elementen)
let tupel1 = (1, 2)
let tupel2 = (1, 2)
if tupel1 == tupel2 {
print("Die beiden Tupel sind identisch.")
}
// das folgende Beispiel funktioniert nicht, weil die Tupel zu viele Elemente haben
let tupel3 = (1, 2, 3, 4, 5, 6, 7)
let tupel4 = (1, 2, 3, 4, 5, 6, 7)
if tupel3 == tupel4 {
print("Die beiden Tupel sind identisch.")
}
Deprecated: Tupel Splat
Und weil wir schon bei Tupel sind: Die wenig bekannte Tuple-Splat-Syntax, die es erlaubt, ein Tupel mit n Elementen an eine Funktion/Methode mit ebenso vielen Parametern zu übergeben, gilt nun als deprecated und wird in Swift 3 ganz verschwinden. Der Grund: Der Code ist schwer zu lesen und stiftet Verwirrung. Der Aufruf g(tupel)
sieht so aus, als würde an g
nur ein Parameter übergeben.
func g(a a:Int, b:Int, c:Int) -> Int {
return a+b+c
}
let tupel = (a:2, b:4, c:8)
print( g(tupel) ) // Ausgabe: 14
Deprecated: Inkrement- und Dekrement-Operator
Die Operatoren ++
und --
gelten als deprecated. In vielen Fällen können Sie i++
oder ++i
einfach durch i+=1
ersetzen. Wenn Sie aber den bisherigen oder aktuellen Wert gleichzeitig an eine Funktion/Methode übergeben, dann müssen Sie Ihren Code umbauen:
// in Swift 2.2 deprecated, aber noch erlaubt
var x=3
while(x>0) {
print(--x)
}
// Swift-3-kompatibler Code
var x=3
while(x>0) {
x-=1
print(x)
}
Deprecated: Die klassische for-Schleife
Die klassische, aus C vertraute for
-Schleife wird in Swift 2.2 letztmalig akzeptiert. Die Entwickler argumentieren, dass sich der Code in den meisten Fällen eleganter formulieren lässt — und oft trifft dies auch zu, vor allem wenn die zu verarbeitenden Daten ohnedies bereits in Arrays, Sets oder anderen Aufzählungsklassen vorliegen. Bei anderen Aufgabenstellungen ist der Verzicht auf die klassische for
-Schleife hingegen lästig und zwingt zu while
-Schleifen oder anderen Konstrukten, die den Code in der Regel nicht besser lesbar machen. Insofern ist die Abschaffung der for
-Schleife nicht vollständig nachvollziehbar.
Wie dem auch sei … Einfache Schleifen im Stil von for var i=start; i<end; i++
machen wenig Probleme und können mit for i in start..<end
formuliert werden. Xcode unterstützt Sie dabei mit Fix-it-Vorschlägen.
// Swift 2.2: deprecated, aber OK
let max=3 // exklusive
for var i=0; i<max; i++ {
print(i)
}
// Lösung für Swift 3
for i in 0 ..< max {
print(i)
}
Schon schwieriger ist es, eine Schleife rückwärts zu durchlaufen:
// Swift 2.2: deprecated, aber OK
for var i = max-1; i>=0; i-=1 {
print(i)
}
// Lösung für Swift 3
for i in (0..<max).reverse() {
print(i)
}
// alternative Lösung für Swift 3
var i = max-1
while(i>=0) {
print(i)
i-=1
}
Schleifen mit Fließkommavariablen sind generell selten eine gute Idee. Höchste Zeit, den Code umzustellen!
// Swift-2.2-Code, +0.0001 wegen möglicher Rundungsfehler
for var x=0.0; x <= 2 * M_PI + 0.0001; x += M_PI/10 {
print(x)
}
// besserer Code, Swift-3-kompatibel
for n in 0...20 {
print(M_PI / 10.0 * Double(n))
}
Am allgemeingültigsten ist immer der Umbau von for
nach while
:
// in Swift 2.2 noch erlaubt
for var x=1.0; x<100; x*=1.3 {
print(x)
}
// Swift-3-kompatibler Code
var x=1.0
while(x<100) {
print(x)
x*=1.3
}
Neu: typealias versus associatedtype
In Swift 2 hat das Schlüsselwort typealias
zwei Bedeutungen: Einerseits wird es — seinem Namen entsprechend — verwendet, um einen Alias für einen vorhandenen Datentyp zu definieren. Andererseits dient es zur Deklaration von generischen Typen in Protokollen. Beginnend mit Swift 3 muss für diesen zweiten Fall das neue Schlüsselwort associatedtype
verwendet werden:
// Swift-2-Code, wird in 2.2 mit deprecated-Warnung akzeptiert
protocol Generator {
typealias Element
mutating func next() -> Element?
}
// korrekter Swift-3-Code
protocol Generator {
associatedtype Element
mutating func next() -> Element?
}
// noch logischer wäre meiner Ansicht nach
// protocol Generator<Element> { ... }
// diese Syntax ist aber weder in Swift 2 noch in Swift 3 zulässig
Neue Selektor-Syntax
Momentan müssen Referenzen auf Methoden (action
-Parameter) in der Objective-C-Syntax als Zeichenketten angegeben werden. Der Swift-Compiler kann diese Zeichenkette nicht verifizieren. Bei Tipp- oder Syntaxfehlern tritt zu Laufzeit ein Fehler auf. In Swift 2.2 kann der Selektor in der Form #selector(Klasse.methode)
bzw. #selector(Klasse.methode(parameter ...))
definiert werden. Ab Swift 3.0 ist diese Syntax zwingend. Das folgende Beispiel illustriert die Syntax. Xcode hilft bei der Umwandlung mit Fix-its.
// deprecated ab Swift 2.2
btn.addTarget(self,
action: "buttonAction:",
forControlEvents: .TouchUpInside)
// erlaubt ab Swift 2.2, erforderlich ab Swift 3
btn.addTarget(self,
action: #selector(ViewController.buttonAction(_:)),
forControlEvents: .TouchUpInside)
Neu: Code-Zweige für verschiedene Swift-Versionen
Sie können in den Swift-Code nun verschiedene Zweige einbauen, die je nach Swift-Version berücksichtigt bzw. ignoriert werden:
#if swift(>=3)
print("Ein Blick in die Zukunft")
#else
print("Noch mit Swift 2.n unterwegs")
#endif
Neu: Schlüsselwörter als Parameternamen
Die meisten Swift-Schlüsselwörter dürfen ab Swift 2.2 als Parameternamen verwendet werden. Insbesondere ist nun in
als Parametername erlaubt. Innerhalb der Funktion müssen derartige Parameternamen in nach rechts gerichtete Apostrophe (Backticks) gestellt werden.
func f(in in:Int, inout out:Int) {
out = `in` * 2
}
var x:Int = 0
f(in:2, out: &x)
print(x) // Ausgabe 4
Deprecated: var-Parameter
Parameter von Funktionen und Methoden können momentan mit dem zusätzlichen Schlüsselwort var
gekennzeichnet werden. Das bedeutet, dass diese Parameter innerhalb der Funktion/Methode verändert werden darf. Die Veränderung gilt allerdings nur innerhalb der Funktion/Methode, nicht aber nach außen hin. Das ist selten zweckmäßig und stiftet außerdem eine Menge Konfusion mit dem im vorigen Beispiel eingesetzten Schlüsselwort inout
, das zur Deklaration von Referenz-Parametern dient. inout
wird es weiterhin geben, aber var
-Parameter gelten beginnend mit Swift 2.2 als deprecated und werden in Swift 3 ganz verschwinden.
// var-Parameter sind jetzt deprecated und ab Swift 3 nicht mehr zulässig
func h(var a:Int) {
a+=1
print(a)
}
h(3) // Ausgabe 4
Sonstiges
- removeFirst(): Für Arrays und andere Datentypen, die das Protokoll
RangeReplaceableCollectionType
implementieren, gibt es jetzt auch die praktische MethoderemoveFirst
. (removeLast
gab es ja schon immer.) -
Neue Schlüsselwörter in Markdown-Kommentaren: In Markdown-Kommentaren konnten Sie schon bisher Schlüsselwörter wie
parameter name:
,returns:
undthrows:
verwenden, um die Parameter eine Methode/Funktion zu dokumentieren, den Rückgabewert zu beschreiben oder auf mögliche Fehler hinzuweisen. Zu diesen Schlüsselwörtern kommen nunkeyword:
,recommended:
undrecommendedover:
hinzu. -
Naming Functions with Argument Labels: Schon bisher konnten Sie Funktionen/Methoden als Referenz übergeben oder in einer Variablen speichern (
let myfunc = someView.insertSubview
). Diese Syntax ist aber problematisch, wenn es mehrere gleichnamige Varianten der Funktion/Methode gibt, die sich nur durch die Parameterliste unterscheiden. Neu in Swift 2.2 ist die Möglichkeit, nun auch die Parameter anzugeben um so klar zu machen, welche Variante Sie meinen:let myfunc = someView.insertSubview(_:aboveSubview:)
-
Constraining AnySequence.init: Die
init
-Funktion vonAnySequence
hat sich geändert. Wenn Sie eigene Klassen vonAnySequence
abgeleitet haben, müssen Sie gegebenenfalls dereninit
-Code anpassen. -
getDemangledTypeName: Die nie dokumentierte Funktion
_stdlib_getDemangledTypeName
ist verschwunden. Den Typ einer Instanz ermitteln Sie am besten mitString(obj.dynamicType)
. Die Ergebnisse sind allerdings nicht immer exakt dieselben. Beispielsweise lieferte_stdlib_getDemangledTypeName
den TypnamenNSDate
, währendString(mydate.dynamicType)
die Zeichenkette__NSDate
zurückgibt. -
#file, #line etc.: Im Programmcode können Sie mit
__FILE__
,__LINE__
etc. auf den Dateinamen, die aktuelle Zeile etc. zugreifen, z.B. um diese Daten in Debug-Code zu integrieren. Diese Schreibweise gilt nun als deprecated. Neu und optisch weit weniger aufdringlich ist die neue Syntax#file
,#line
,#column
,#function
. Beispiel:let fname = #file
oderlet linenr = #line
.
Geplant, aber noch nicht implementiert
Neuerungen im Playground
Die Gestaltungs- und Steuerungsmöglichkeiten in Playgrounds werden weiter aufgewertet, vermutlich, damit diese Dokumente sich noch besser zum Einsatz für Dokumentation und Unterricht eignen. So können nun auch Videos eingebettet werden, sofern diese zuvor den Ressourcen des Playgrounds hinzugefügt wurden.
![Beschriftung](filename.mp4 width="640" height="480" poster="vorschaubild.png")
Mit gewissen Einschränkungen sind in Playgrounds nun Live-Interaktionen mit per Playground-Code erzeugten iOS- oder OS-X-Steuerelementen erlaubt.
Hinter den Kulissen wurde die Interna der Playground-Darstellung verändert. Das ist unter anderem daran erkennbar, dass Markdown-Kommentare jetzt einer anderen Schrift angezeigt werden.
Unverändert läuft Code in Playgrounds relativ langsam. Bei der Eingabe neuen Codes kommt es immer wieder zu Problemen. Bei meinen Tests brach die Kommunikation zwischen dem Playground und dem Swift-Compiler immer wieder ab (failed to launch stub for playground execution). Manchmal gelingt die Wiederaufnahme der Kommunikation, andernfalls ist ein Neustart von Xcode notwendig.
Beispieldateien zu meinem Swift-2-Buch
Alle Beispieldateien meines Swift-2-Buchs liegen nun auch in einer überarbeiteten Fassung für Swift 2.2 vor. Die Beispiele sind nun frei von deprecated-Warnungen. Die Top-Drei der Änderungen waren: for
-Schleifen, x++/x--
sowie Selektoren. Insgesamt war der Umbau aller Beispiele in ca. einem halben Tag erledigt.
Beispieldateien Swift 2.2 (ZIP)
Quellen
- Xcdeo 7.3 Beta 5 Release Notes (erfordert Apple-Developer-Account)
- https://swift.org/blog/swift-2-2-release-process
- http://ericasadun.com/2016/01/26/welcoming-our-new-swift-2-2-overlords
- http://ericasadun.com/2016/02/22/beta-4-zut-alors-whats-new-in-swift
- http://ericasadun.com/2016/01/26/xcode-7-3-beta-2-introduces-live-interactive-playgrounds
- http://ericasadun.com/2016/03/01/beta-5-embedding-video-in-playgrounds
- https://www.hackingwithswift.com/swift2-2
- https://lists.swift.org/pipermail/swift-evolution
Implementierte oder geplante Proposals für Swift 2.2
- https://github.com/apple/swift-evolution/blob/master/proposals/0001-keywords-as-argument-labels.md
- https://github.com/apple/swift-evolution/blob/master/proposals/0004-remove-pre-post-inc-decrement.md
- https://github.com/apple/swift-evolution/blob/master/proposals/0007-remove-c-style-for-loops.md
- https://github.com/apple/swift-evolution/blob/master/proposals/0008-lazy-flatmap-for-optionals.md
- https://github.com/apple/swift-evolution/blob/master/proposals/0014-constrained-AnySequence.md
- https://github.com/apple/swift-evolution/blob/master/proposals/0015-tuple-comparison-operators.md
- https://github.com/apple/swift-evolution/blob/master/proposals/0020-if-swift-version.md
- https://github.com/apple/swift-evolution/blob/master/proposals/0021-generalized-naming.md
- https://github.com/apple/swift-evolution/blob/master/proposals/0022-objc-selectors.md
- https://github.com/apple/swift-evolution/blob/master/proposals/0028-modernizing-debug-identifiers.md
dynamicType und getDemangledTypeName
- https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Types.html
- http://stackoverflow.com/questions/27912078/where-are-stdlib-gettypename-stdlib-getdemangledtypename-declared
- http://stackoverflow.com/questions/35036173/replacement-for-stdlib-getdemangledtypename-in-swift-2-2