Hallo, ich heiße Ilya. Ich bin ein iOS-Entwickler bei Tinkoff.ru. In diesem Artikel werde ich einen kurzen Überblick über die wichtigsten Änderungen in Swift 5 geben. Diese Änderungen werden in den 
Versionshinweisen beschrieben . Für diejenigen, die sich noch nicht vertraut gemacht haben, willkommen bei cat!

Die Größe der Anwendung wird verringert!
In Swift 5 geschriebene und für iOS 12.2, watchOS 5.2, tvOS 12.2 kompilierte Anwendungen enthalten keine dynamischen Bibliotheken für die Swift-Standardbibliothek und das Swift SDK. Dies bedeutet, dass die Größe der Anwendung jedoch nicht wesentlich abnimmt. Wenn Sie 
diesem Tweet glauben, wurde die Größe des leeren Projekts von 2,4 MB auf 24 KB reduziert. Ein gutes Ergebnis für kleine Anwendungen, aber für große Anwendungen gibt es keinen großen Unterschied.
@dynamicCallable ( SE-0216 )
Mit 
dem Attribut 
@dynamicCallable können 
Sie mit einem Objekt als Funktion arbeiten. Solche Objekte werden Funktionsobjekte oder Funktoren genannt (weitere Details finden Sie 
hier ). Funktionale Objekte befinden sich in C ++, Python, JavaScript und anderen Sprachen. In Swift wurden sie hinzugefügt, um die Kompatibilität mit diesen Sprachen zu gewährleisten. Tatsache ist, dass Swift jetzt gut mit API C und Objective-C interagiert und Sprachentwickler die Interaktion mit dynamischen Sprachen hinzufügen möchten - Python, JavaScript, Ruby und anderen.
Um einen Typ zu einem Funktor zu machen, müssen Sie das Attribut 
@dynamicCallable zu seiner Deklaration hinzufügen. Stellen Sie sich ein Beispiel für eine 
Reducer- Struktur vor, mit der Sie einem Array Zahlen hinzufügen können:
@dynamicCallable struct Reducer { ... } 
Dann müssen Sie eine oder beide der folgenden Methoden implementieren:
 func dynamicallyCall(withArguments: ExpressibleByArrayLiteral) func dynamicallyCall(withKeywordArguments: ExpressibleByDictionaryLiteral) 
Mit der ersten Funktion können Sie auf das Objekt zugreifen, indem Sie ein Array als Argumente übergeben. Mit der zweiten Funktion können Sie auf das Objekt zugreifen, indem Sie dasselbe Array wie die Argumente übergeben, jedoch die Namen der Argumente verwenden.
Eine Implementierung der ersten Funktion für eine 
Reducer- Struktur würde beispielsweise folgendermaßen aussehen:
 func dynamicallyCall(withArguments arguments: [Int]) -> Int { return arguments.reduce(0, +) } 
Wenden Sie dann eine solche Struktur wie folgt an:
 let reducer = Reducer() let sum = reducer(1, 2, 3)  
Wir werden die Implementierung der zweiten Methode am Beispiel der 
Komparatorstruktur betrachten , mit der wir zwei Zahlen vergleichen können:
 @dynamicCallable struct Comparator { func dynamicallyCall(withKeywordArguments arguments: KeValuePairs<String, Int>) -> ComparisonResult { guard let lhs = arguments["lhs"], let rhs = arguments["rhs"], lhs != rhs else { return .orderedSame } return lhs > rhs ? .orderedDescending : .orderedAscending } } 
Sie können diese Struktur wie folgt verwenden:
 let comparator = Comparator() let comparisionResult = comparator(lhs: 1, rhs: 2)  
Viele Menschen wissen, dass es bei der Verarbeitung von Aufzählungswerten erforderlich ist, alle Fälle zu beschreiben und nicht die Standardeinstellung zu verwenden. Diese Anforderung erhöht zwar die Sicherheit, hat jedoch auch einen Nachteil, da Sie beim Ändern von Werten in der Aufzählung deren Verarbeitung hinzufügen müssen. Es besteht immer noch die Möglichkeit, dass das 
Systemframework eine der Aufzählungen ändert, dies wurde jedoch in Ihrer Anwendung nicht verarbeitet (z. B. mit 
LABiometryType ).
Swift 5 fügt das 
unbekannte Attribut hinzu, mit dem Sie bei der Verarbeitung einer Aufzählung zwei verschiedene Szenarien trennen können:
- Der Standardcode sollte für alle Fälle ausgeführt werden, die nicht im Switch verarbeitet wurden
- Alle Fälle werden in switch verarbeitet. Wenn neue hinzugefügt werden, müssen Sie standardmäßig den Code verwenden
Schauen wir uns ein Beispiel an:
 enum HTTPMethod { case post, get, put }  
Double Optional als Ergebnis des Aufrufs einer Funktion mit try loswerden? ( SE-0230 )
Sicherlich sind viele auf die Tatsache gestoßen, dass beim Aufrufen der Throwable-Funktion, die 
Optional zurückgibt, 
try? Das Ergebnis ist ein Typ, der in zwei 
optionale Optionen eingeschlossen ist . Dies ist nicht sehr praktisch, und rufen Sie in Swift 5 
try an? In diesem Fall wird ein Typ zurückgegeben, der nur in eine 
Option eingeschlossen ist .
So war es vor Swift 5:
 let result = try? optionalObject?.foo()  
Und so wird es in Swift 5 sein:
 let result = try? optionalObject?.foo()  
Multiplizitätsprüfung ( SE-0225 )
Um die Vielzahl einer Zahl zu einer anderen zu überprüfen, können Sie anstelle des Restes der Division (%) die Funktion 
isMultiple (of :) verwenden :
 
Die Änderung ist geringfügig, macht den Code jedoch etwas klarer und vereinfacht die Suche nach Code.
Zählen der Anzahl der Elemente in einer Sequenz mit einer Bedingung ( SE-0220 )
In Swift 5 fügt der Sequenztyp die Methode 
count (wobei: (Element) -> Bool) -> Int hinzu , mit der Sie die Anzahl der Elemente in einer Sequenz zählen können, die eine bestimmte Bedingung in einem Durchgang erfüllen. Vorher musste ich 
Filter in Verbindung mit 
count verwenden . Diese Methode speichert den zugewiesenen Speicher, wenn ein neues Array in der 
Filtermethode erstellt wird.
Ein Beispiel:
 let countOfZeroes = [0, 1, 2, 0, 4].count(where: { $0 == 0 })  
CompactMapValues-Methode im Wörterbuch ( SE-0218 )
Diese Methode kombiniert 
compactMap aus 
Array und 
mapValues aus 
Dictionary . Durch Aufrufen dieser Methode wird ein Wörterbuch mit transformierten Werten erstellt, in dem keine Werte gleich 
Null vorhanden sind .
Ein Beispiel:
 let dictionary = ["a": "1", "b": "2", "c": "Number"] let resultDictionary = dictionary.compactMapValues { Int($0) }  
Rohe Saiten ( SE-0200 )
Es wurde die Möglichkeit hinzugefügt, Zeilen zu schreiben, in denen Anführungszeichen und Backslashes als reguläre Zeichen und nicht als Sonderzeichen verwendet werden. Fügen Sie dazu das Zeichen # am Anfang und am Ende der Zeile hinzu.
Ein Beispiel:
 let string1 = #"   " ""# let string2 = #"  \ "# 
Wenn Sie beim Erstellen einer Zeile eine Variable einfügen, müssen Sie nach dem Backslash das # -Zeichen hinzufügen:
 let string = #"   \#(variable)"# 
Wenn die Zeile ein # -Zeichen hat, müssen Sie am Anfang und am Ende der Zeile zwei ## -Zeichen hinzufügen:
 let string = ##"   #"## 
Das Sequenzprotokoll enthält keine zugeordnete SubSequence vom Typ ( SE-0234 )
Der assoziative Typ von 
SubSequence wurde aus dem 
Sequenzprotokoll in 
Collection verschoben 
. Jetzt geben alle Methoden in 
Sequence , die 
SubSequence zurückgegeben haben, einen bestimmten Typ zurück. Beispielsweise gibt die 
Suffix- Methode jetzt ein 
Array zurück . Hier ist die vollständige Liste der von dieser Änderung betroffenen Methoden:
 extension Sequence { public func dropFirst(_ k: Int = 1) -> DropFirstSequence<Self> public func dropLast(_ k: Int = 1) -> [Element] public func suffix(_ maxLength: Int) -> [Element] public func prefix(_ maxLength: Int) -> PrefixSequence<Self> public func drop(while predicate: (Element) throws -> Bool) rethrows -> DropWhileSequence<Self> public func prefix(while predicate: (Element) throws -> Bool) rethrows -> [Element] public func split( maxSplits: Int = Int.max, omittingEmptySubsequences: Bool = true, whereSeparator isSeparator: (Element) throws -> Bool ) rethrows -> [ArraySlice<Element>] } 
Jetzt wird die Arbeit mit diesen Methoden einfacher.
Protokollbeschränkungen
Protokolle unterstützen jetzt die Einschränkung in Form von Klassen, die dieses Protokoll implementieren. Mit anderen Worten, Sie können jetzt angeben, dass ein Protokoll nur von einer bestimmten Klasse implementiert werden kann. Zum Beispiel:
 protocol Viewable: UIView {} protocol Viewable where Self: UIView {} 
Die zweite Aufnahmeoption wird in Swift 4.2 unterstützt, kann jedoch einen Kompilierungsfehler oder eine Laufzeit verursachen. In Swift 5 tritt dieser Fehler nicht auf.
Fazit
Dies ist keine vollständige Liste der Änderungen in Swift 5, hier werden nur die wichtigsten Änderungen erfasst. Im Allgemeinen sind die vorgestellten Änderungen positiv und machen die Sprache verständlicher und flexibler. Die Hauptsache ist, dass "In aktuelle Swift-Syntax konvertieren" schmerzlos sein sollte.
Das ist alles, danke fürs Lesen.