Neu in Swift 3.0 und Xcode 8

Swift 3.0 ist fertig. Seit 7. September 2016 ist Xcode 8 als Gold Master (GM) für alle Teilnehmer des Apple-Developer-Programms verfügbar, in ein paar Tagen wird die finale Version kostenlos im App Store auftauchen. Was ist also neu?

Updates 17.9.2016, 20.9.2016: Noch mehr Details sowie Xcode-Screenshots.

98 realisierte Detailveränderungen

Der Entwicklungsprozess von Swift 3.0 ist öffentlich verlaufen. Daher sind die geplanten und tatsächlich durchgeführten Änderungen schon seit Monaten bekannt (siehe auch Pläne für Swift 3). Eine vollständige, wenn auch nicht gerade lesefreundliche Zusammenstellung aller Neuerungen finden Sie in dieser Liste:

http://apple.github.io/swift-evolution

swift3-implementation

Diese Liste fasst alle in Form offizieller Proposals eingereichter Änderungswünsche zusammen. Aus verschiedenen Gründen wurden nicht alle Ideen tatsächlich realisiert. Der für Swift 3.0 relevante Teil beginnt bei der Überschrift Implemented for Swift 3. Das sind 90 Punkte. Dazu kommen acht Vorschläge, die bereits in Swift 2.2 realisiert wurden — macht also, wenn man Swift 2.1 als Maßstab nimmt, 98 Änderungen von Swift 2.n zu Swift 3.0.

Eine kompakte Zusammenstellung der wichtigsten Änderungen bieten darüber hinaus die Release Notes, die aktuell nur für Apple-Developer-Mitglieder zugänglich sind.

Außerdem wurde das von Apple verfasste Swift-Handbuch auf Swift 3 adaptiert.

An Lesestoff scheitert es also nicht …

Die Spreu vom Weizen trennen

98 Änderungen klingt dramatisch — aber zum Teil handelt es sich um Kleinigkeiten (z.B. die Umbenennung von flatten in joined, Proposal 0133), zum Teil um die Verfeinerung bzw. um die exakte Formulierung von Syntaxfeinheiten (z.B. der Umgang mit Enumerations-Elementen, Proposal 0036). Deswegen möchte ich mich in den weiteren Abschnitten auf meine persönlichen Favoriten unter den Swift-3-Neuerungen konzentrieren.

Swift-freundlichere Bibliotheken

Die für App-Entwickler wichtigste Neuerung hat gar nicht mit der Swift-Syntax an sich zu tun, sondern vielmehr mit der Schnittstelle zu den vielen, teilweise schon seit Jahren verfügbaren Bibliotheken (Cocoa, UIKit, Foundation usw.). Diese Bibliotheken wurden allesamt für Objective C entwickelt. Die Nutzung der dort definierten Klassen, der Aufruf der Methoden erwies sich in Swift als umständlich und ganz und gar unswifty.

Nun kann selbst Apple nicht alle Bibliotheken neu schreiben. Stattdessen hat man sich dazu entschlossen, parallel zur Objective-C-Schnittstelle eine zweite Swift-Schnittstelle zu den Bibliotheken zu schaffen, die den Gepflogenheiten von Swift besser entspricht und die zu klarerem und oft auch etwas kürzerem Code führt.

Einige Beispiele, immer zuerst in der Swift-2- und dann in der Swift-3-Version:

NSUserDefaults.standardUserDefaults()  -->
UserDefaults.standard

func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)  -->
func prepare(for segue: UIStoryboardSegue, sender: Any?)

let dest = segue.destinationViewController  -->
let dest = segue.destination

txt.stringByTrimmingCharactersInSet(
  NSCharacterSet.whitespaceAndNewlineCharacterSet())    -->
txt.trimmingCharacters(in: .whitespacesAndNewlines)

Außerdem wurden viele Klassen der Foundation-Bibliothek umbenannt, z.B.:

NSBundle          --> Bundle
NSDate            --> Date
NSFileManager     --> FileManager
NSFormatter       --> Formatter
NSLocal           --> Locale
NSNumberFormatter --> NumberFormatter
NSTask            --> Process (!!)
NSThread          --> Thread
NSURL             --> URL
NSURlxxx          --> URLxxx

Schließlich wurden viele Swift-eigene Klassen der Standard Library optimiert, insbesondere was den Umgang mit Aufzählungen (Sequences) betrifft.

Basis für diese Anpassungen waren die folgenden Proposals:

Konsistenter Umgang mit den Parametern von Methoden, Funktionen und Attributen

Ein Relikt aus Objective-C-Zeiten war Swifts Umgang mit den Parametern von (Init)-Funktionen, Methoden und Attributen. Mal war der erste Parameter automatisch unbenannt, dann wieder nicht. Noch chaotischer wäre es kaum gegangen.

Mit Swift 3 ist damit Schluss. Es gelten nun für alle Parameter dieselben Regeln. Außerdem wurden einige syntaktische Feinheiten geklärt bzw. vereinfacht. Das betrifft z.B. die Reihenfolge, in der Default-Parameter übergeben werden müssen, sowie den Umgang mit inout-, var– und let-Parametern. Das folgende Listing gibt einen Überblick über die aktuelle Syntax zur Deklaration von Paramtern:

func f() { ... }                    // kein Parameter

func f(para: Int) { ... }           // gewöhnlicher Parameter
func f(_ para: Int) { ... }         // unbenannter Parameter
func f(ext para: Int) { ... }       // zweinamiger Parameter  

func f(para: inout Int)  { ... }    // veränderlicher Parameter
func f(_ para: inout Int)  { ... }  // unbenannter ver. Parameter
func f(ext para: inout Int) { ... } // zweinamiger ver. Parameter

func f(para: Int = 0) { ... }       // optionaler Parameter
func f(_ para: Int = 0) { ... }     // unbenannter opt. Parameter 
func f(ext para: Int = 0) { ... }   // zweinamiger opt. Parameter

func f(para: Int ...) { ... }       // variadischer Parameter
func f(_ para: Int ...) { ... }     // unbenannter var. Parameter
func f(ext para: Int ...) { ... }   // zweinamiger var. Parameter

Die Konzepte aller Änderungen sind hier zusammengefasst:

Generics

Apple hat große Pläne, was die Optimierung der generischen Funktionen in Swift anbelangt. Von diesen Plänen ist bisher aber nur ein Teil realisiert. So gibt es jetzt generische Typen-Aliase, where-Bedingungen für generische Parameter werden lesbarer formuliert, generische Protokolle klarer formuliert.

// generische Typ-Aliase
typealias StringDictionary<T> = Dictionary<String, T>
typealias IntFunction<T> = (T) -> Int
typealias MatchingTriple<T> = (T, T, T)
typealias BackwardTriple<T1,T2,T3> = (T3, T2, T1)

// Position von 'where' nach Parameterliste und Rückgabetyp
func toArray<S: Sequence, T> (_ seq : S) -> [T]
  where T == S.Iterator.Element
{ ... }

// generische Protokolle mit »associatedtype«
protocol Generator {
  associatedtype Element  // statt bisher: typealias Element  
  mutating func next() -> Element?
}

Sonstige Neuerungen

Swift hat das Overloading bzw. die Neudefinition von Operatoren schon in der ersten Version sehr leicht gemacht. Jetzt gibt es eine neue Syntax, um die Priorität neuer Operatoren besser zu definieren. Sehr nett.

Bisher konnten öffentliche Klassen (public) gleichermaßen verwendet und abgeleitet werden. Wer seine Klasse als public deklarierte, erlaubt also nicht nur die Nutzung der Klasse, sondern auch ihre Verwendung als Basis für eigene, abgeleitete Klassen. In Zukunft erlaubt public nur die Nutzung der Klasse. Ist die Klasse auch als Basis für andere, vererbte Klassen vorgesehen, muss sie als open deklariert werden. Analog bedeutet public bei Methoden, dass die Methode aufgerufen werden kann. Darf die Methode auch überschrieben (überladen) werden, muss sie mit open deklariert werden.

Insgesamt gibt es jetzt fünf Schlüsselwörter zur Zugriffssteuerung, deren Bedeutung im folgenden Listing kurz skizziert ist:

open         // Zugriff und Vererbung in anderen Modulen
public       // Zugriff auch in anderen Modulen, 
             // aber Vererbung nur im eigenen Modul
internal     // Zugriff und Vererbung nur im eigenen Modul
fileprivate  // Zugriff und Vererbung nur in der aktuellen Datei
private      // Zugriff nur in der aktuellen Klasse

Nicht so toll

Nicht alle Neuerungen sind aus meiner Sicht Verbesserungen. Mit der Abschaffung der Operatoren ++ und -- kann ich persönlich gut leben. x+=1 ist für mich in der Regel gut genug.

Aber dass die klassische for-Schleife eliminiert wurde, finde ich einfach nur idiotisch. Hier hat der Wahnsinn Methode. Das Argument, for-Schleifen wären schwer zu lesen oder unswifty, ist einfach absurd — nahezu jede andere Programmiersprache hat solche Schleifen, jeder Programmierer, jede Programmiererin lernt den Umgang mit solchen Schleifen in der ersten oder zweiten Stunde.

Natürlich gibt es viele Fälle, wo for-Schleifen in Swift unkompliziert mit for-in nachgebildet werden können (for i in 1...3, for item in myArray). Aber in allen anderen Fällen sind nun wesentlich umständlichere Konstruktionen mit while, stride oder reversed notwendig. Klarerer, effizienterer Code resultiert daraus eher selten.

Hier sind die durchaus heiß diskutierten Proposals:

In der Motivation schon eher verständlich, in der Auswirkungen aber auch nicht immer toll, ist die Abschaffung impliziter (automatischer) Typumwandlungen zwischen Swift-Typen und Objective-C-Typen. Swift war bei Typumwandlungen schon bisher restriktiv, jetzt wird es noch schlimmer. Keine Zeile ohne Casting. (Na ja, ich übertreibe mal wieder …)

Xcode 8

Die größte Neuerung von Xcode 8 besteht natürlich in der Unterstützung von Swift 3. Aber es gibt noch mehr Verbesserungen :-)

  • Im Storyboard-Editor können Sie nun in beliebigen Zoom-Stufen arbeiten.

  • Bei iOS-Apps können Sie direkt im Storyboard-Editor die Views blitzschnell zwischen verschiedenen iOS-Geräten sowie zwischen Hoch- und Querformat umstellen. Kein umständliches Hantieren mit der Preview-Ansicht, keine quadratischen Views mehr. Sehr gut.

  • Farben und Bitmaps aus Xcassets-Dateien können im Code als Literale eingebaut werden. Diese Literale zeigen die Farbe bzw. eine winzige Vorschau der Bitmap. Eine Kleinigkeit, aber ungemein praktisch!

  • Der Code-Konverter, der Ihre Projekte von Swift 2 auf Swift 3 umstellt, funktioniert größtenteils sehr gut. Besonders schnell gelingt der Umstieg, wenn Sie Ihren Code zuvor schon an Swift 2.2 angepasst haben.

  • Das Signing wurde verbessert. Zum einen kann Xcode nun auf mehreren Rechnern einen Developer Account nutzen, ohne dass es Konflikte gibt. Zum anderen löst das neue Auto Signing viele Probleme. Insbesondere ist es beim Einreichen einer App nicht mehr notwendig, Distribution Provisioning Profiles manuell einzurichten — Xcode kann das jetzt automatisch.

Ärgerlich finde ich, dass es immer noch keine Refactoring-Unterstützung für Swift gibt. Gerade die ständigen Umbauten an Swift machen oft auch umfassende Änderungen im eigenen Code notwendig. Da könnte Xcode gerne ein wenig mithelfen.

Die Stabilität von Xcode ist aus meiner Sicht OK, aber hier kann sicher noch gefeilt werden. Richtige Abstürze habe ich bisher keine bemerkt, aber dass der Playground den Kontakt zum Compiler verliert, passiert ständig. Etwas seltener geschieht dies in richtigen Projekten — plötzlich funktioniert die Auto-Vervollständigung nicht mehr.

Ein weiteres Ärgernis alter Xcode-Versionen wartet auf Behebung: Bereits behobenen Syntaxfehler werden weiter als Fehler gekennzeichnet, bis mit cmd+B oder cmd+R ein neuerliches Kompilieren erzwungen wird. Hoffen wir also auf ein baldiges Xcode 8.0.1.

Der in Xcode integrierte Konvertier von Swift 2 zu Swift 3 funktioniert überraschend gut.
Der in Xcode integrierte Konvertier von Swift 2 zu Swift 3 funktioniert überraschend gut.
Das Arbeiten im Storyboard-Editor hat erheblich an Komfort gewonnen
Das Arbeiten im Storyboard-Editor hat erheblich an Komfort gewonnen
Mit Bitmap- und Farbliteralen kann der Code visuell ansprechend gestaltet werden.
Mit Bitmap- und Farbliteralen kann der Code visuell ansprechend gestaltet werden.
Das Signing von Apps bereitet in Xcode 8 weniger Probleme als bisher.
Das Signing von Apps bereitet in Xcode 8 weniger Probleme als bisher.

Swift-3-Buch

Die umfassende Berichterstattung über Swift 3 in diesem Blog hat natürlich damit zu tun, dass ich seit Monaten intensiv(st) an der Neuauflage meines Swift-Buchs arbeite. Ein paar Details kann ich schon verraten:

  • Das Buch geht naturgemäß auf alle Neuerungen von Swift 3 ein.
  • Es berücksichtigt neben iOS und macOS auch tvOS.
  • Ein weiterer neuer Schwerpunkt ist SpriteKit (2D-Spiele-Programmierung mit mehreren Beispielen inklusive einem Pac-Man-Clone).
  • Das Buch ist vollkommen neu in kleinere Kapitel strukturiert. Ich habe mich bemüht, das Buch in einer Art Baukasten-Konzept zusammenzusetzen, so dass die Kapitel möglichst unabhängig voneinander sind. Auch sind alle großen Beispiele nun von den Grundlagenkapiteln getrennt.
  • Der Umfang wird auf vorauss. knapp 1200 Seiten anwachsen.
  • Der Erscheinungstermin ist vorauss. Ende November.

swift3

 oder  oder  EDV-BUCHVERSAND Delf Michel

2 Gedanken zu „Neu in Swift 3.0 und Xcode 8“

  1. Hallo, ich habe gerade mal auf swift.io nachgesehen und leider wird immer noch ausschließlich Ubuntu unterstützt. Weißt Du evtl. mehr? Gibt es Pläne, Swift auch auf anderen Distris zu portieren? Oder geht das gar schon und ich hab’s nur nicht gefunden?

    1. Es gibt ja den Quellcode, d.h. wer will, kann es sich selbst kompilieren.

      Persönlich habe ich auch den Eindruck, dass das Linux-Engagement Apples momentan sehr halbherzig ist. Auch die Ubuntu-Unterstützung ist ja mager, wen interessiert Swift für 15.10? Warum keine Paketquellen? Eine für Debian/Ubuntu, eine für Red Hat / Fedora …

      Die besten Infos zu Swift und Linux gibts aktuell auf http://dev.iachieved.it. Siehe insbesondere:

      http://dev.iachieved.it/iachievedit/swift-3-0-for-ubuntu-16-04-xenial-xerus

Kommentare sind geschlossen.