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.