Swift 4.0 vs Swift 3.0 - Unterschiede und neue Funktionen

Veröffentlicht: 2021-10-05

Der Tag, an dem Apple eine neue Version der bekannten Swift-Sprache veröffentlicht, hat uns endlich erreicht. Was sollen wir davon erwarten? Zitternd vor Vorfreude haben wir uns entschlossen, einen kleinen Überblick über die neuen Updates zu geben, die in der Swift 4- Version enthalten sein werden.

3 Eckpfeiler von Swift.

Als fantastische Sprache zum Schreiben von Code hat Swift ihre eigenen Vorteile und soll die Objective-C-Sprache „überleben“.

Gerne können Sie sich über die Hauptunterschiede zwischen Swift und Objective-C informieren

Swift ist schnell , typsicher und sehr ausdrucksstark . Es könnte verwendet werden, um Software auf Telefonen und Tablets, Desktops und Servern zu schreiben – anscheinend auf allem, was Code ausführt. Es lädt Sie ein, damit zu spielen - mit Apples Programmierlern-App Swift Playgrounds oder der Verwendung von Playgrounds in Xcode sehen Sie die Ergebnisse Ihrer Arbeit sofort, ohne sich in die Entwicklung und den Betrieb einer App zu stecken. erster Platz. Mit jeder neuen additiven Version wird es besser und schneller, und das ist bei der Swift 4-Version der Fall.
Bereit-ständig?

Ein weiteres großartiges Feature, das Xcode 9 für Swift 4 besitzt - Sie müssen sich über die bevorstehende Migration keine großen Sorgen machen und werden beim Lesen dieses Artikels herausfinden, warum.

Apropos, lassen Sie uns kurz erkunden, welche Bonbons und Swift 4-Neuheiten uns dieser Herbst bringen.

Einstieg

Die Sprache selbst ist ohne eine praktische IDE, die Xcode in der Welt der Entwickler ist, nicht sehr nützlich. Sie können die neueste Version von Xcode 9 vom Mac App Store oder von der Download-Seite auf der Apple Developer-Site herunterladen, aber stellen Sie zunächst sicher, dass Sie über ein aktives Entwicklerkonto verfügen. Es ist ziemlich stabil, sodass Sie Xcode 8 für Ihre täglichen Codierungsroutinen ersetzen können.

Sie können mit xcversion auch mehrere Versionen von Xcode installieren

Wenn Sie ein neues Projekt starten, können Sie loslegen. Wenn Sie jedoch bereits ein in Swift 3.x geschriebenes Projekt haben, müssen Sie einen Migrationsprozess durchlaufen.

Wir empfehlen, zuerst den Playground auszuprobieren - um sich an neue Funktionen zu gewöhnen.

Beim Lesen dieses Artikels werden Ihnen Links zu Swift Evolution-Angeboten im Format "SE-____" auffallen.

Migration zu Swift 4

Die Migration von einer Hauptversion von Swift zur nächsten war schon immer ziemlich intensiv, insbesondere von Swift 2.x auf 3.0. Normalerweise dauert es etwa 1-2 Tage pro Projekt, aber die Migration zu Swift 4 ist etwas einfacher und kann viel schneller durchgeführt werden.

Vorbereitung vor der Migration

Xcode 9 unterstützt nicht nur Swift 4, sondern auch eine Übergangsversion 3.2, sodass Ihr Projekt ohne große Schwierigkeiten kompiliert werden sollte. Dies ist möglich, da der Swift 4-Compiler und das Migrationstool beide Sprachversionen unterstützen. Sie können verschiedene Swift-Versionen pro Ziel angeben. Dies ist sehr hilfreich, wenn einige Bibliotheken von Drittanbietern noch nicht aktualisiert wurden oder wenn Sie mehrere Ziele in Ihrem Projekt haben. Allerdings hat nicht nur die Sprache, sondern auch das SDK einige Änderungen erhalten, daher ist es sehr wahrscheinlich, dass einige Updates auf Ihren Code angewendet werden müssen, da Apple die SDK-APIs weiter aufräumt...

Schnelles Migrationstool

Wie immer bietet Apple ein in Xcode gebündeltes Swift-Migrationstool an, das bei der Migration von einer früheren Swift-Version helfen kann. Sie können es in Xcode starten, indem Sie zu Bearbeiten -> Konvertieren -> In die aktuelle Swift-Syntax ... gehen und auswählen, welche Ziele Sie konvertieren möchten.

Sie werden dann gefragt, welche Objective-C-Inferenzpräferenz Sie anwenden möchten:

Da in Swift 4 die additiven Änderungen dominieren, übernimmt das Swift-Migrationstool die meisten Änderungen für Sie.

Kakaoschoten

Die meisten -Entwickler verwenden CocoaPods Dependency Manager für ihre Projekte, da der Swift Package Manager noch nicht so ausgereift ist, wie er sein könnte, obwohl er sich sehr schnell verbessert. Wie oben erwähnt, wurden noch nicht alle Bibliotheken von Drittanbietern auf Swift 4 aktualisiert, sodass Sie beim Kompilieren einiger davon Fehler sehen konnten. Eine mögliche Lösung, um dieses Problem zu beheben, besteht darin, Swift Version 3.2 für die Pods anzugeben, die noch nicht aktualisiert wurden, indem Sie Podfile post_install ein post_install Skript Podfile :

 old_swift_3_pods = [ 'PodName1', 'PodName2', ] post_install do |installer| installer.pods_project.targets.each do |target| if old_swift_3_pods.include? target.name target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '3.2' end end end end

Dann renne

 pod install

Jetzt können Sie Pods fehlerfrei kompilieren.

Sehen wir uns die Änderungen und Ergänzungen der Swift 4-API an.

API-Änderungen und -Ergänzungen

Saiten

String entspricht jetzt dank des SE-0163-Vorschlags dem Collection . Erinnern Sie sich an Swift 1.x?

Es ist jetzt keine Array-Eigenschaft von characters erforderlich, da Sie direkt über String iterieren können:

 let string = "Hello, Mind Studios!" for character in string { print(character) }

Dies bedeutet auch, dass Sie alle Collection Methoden und -Eigenschaften für String , wie count , isEmpty , map() , filter() , index(of:) und viele mehr:

 string.count // No more `string.characters.count` string.isEmpty // false let index = string.index(of: " ") // 6 let reversedCollection = "abc".reversed() let reversedString = String(reversedCollection) // "cba" // String filtering let string = "ni123n456iniASijasod! 78a9-kasd aosd0" let numbersString = string.filter { Int(String($0)) != nil } // "1234567890"

Neuer Substring

Swift 4 bringt einen neuen Substring Typ, der eine Substring von String (wie in SE-0163 oben erwähnt).

 // Split string into substrings let string = "Hello, Mind Studios!" let parts = string.split(separator: " ") // ["Hello,", "Mind", "Studios!"] type(of: parts.first!) // Substring.Type

Sowohl String als auch Substring jetzt das neue StringProtocol , wodurch sie fast identisch und interoperabel sind:

 var hello = parts.first! // Concatenate a String onto a Substring hello += " !" // "Hello, !" // Create a String from a Substring let helloDog = String(hello) // "Hello, !"

Wichtiger Hinweis

SE-0163 hat einen sehr wichtigen Hinweis:

 Long-term storage of `Substring` instances is discouraged. A substring holds a reference to the entire storage of a larger string, not just to the portion it presents, even after the original string's lifetime ends. Long-term storage of a substring may therefore prolong the lifetime of elements that are no longer otherwise accessible, which can appear to be memory leakage.

Das bedeutet, dass Substring als temporärer Speicher für die String Substring werden soll. Wenn Sie es an einige Methoden oder andere Klassen übergeben möchten, konvertieren Sie es zuerst in String :

 let substring: Substring = ... // Substring let string = String(substring) // String someMethod(string)

Wie auch immer, das Typsystem von Swift hilft Ihnen, Substring nicht an eine Stelle zu übergeben, an der String erwartet wird (vorausgesetzt, Sie verwenden kein neues StringProtocol als Parametertyp).

Mehrzeilige String-Literale

SE-0168 führt eine einfache Syntax für mehrzeilige String-Literale mit drei doppelten Anführungszeichen """ was bedeutet, dass die meisten Textformate (wie JSON oder HTML) oder ein langer Text ohne Escape eingefügt werden können:

 let multilineString = """ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam mattis lorem et leo laoreet fermentum. Mauris pretium enim ac mi tempor viverra et fermentum nisl. Sed diam nibh, posuere non lectus at, ornare bibendum erat. Fusce mattis sem ac feugiat vulputate. Morbi at nunc maximus, vestibulum orci et, dictum neque. Vestibulum vulputate augue ac libero vulputate vestibulum. Nullam blandit et sapien non fermentum. Proin mollis nisl at vulputate euismod. """

Escape-Zeilen in Zeichenfolgenliteralen

SE-0182 fügt die Möglichkeit hinzu, Zeilenumbrüche in mehrzeiligen String-Literalen mit einem umgekehrten Schrägstrich am Ende der Zeile zu maskieren.

 let escapedNewline = """ Line 1, Line 2 \ next part of line 2, Line 3 """ print(escapedNewline)
 Line 1, Line 2 next part of line 2, Line 3

Verbesserte Unicode-Unterstützung

Swift 4 bietet Unterstützung für Unicode 9, was bedeutet, dass die Probleme mit der Zählung von Unicode-Zeichen jetzt behoben sind:

 "".count // 1, in Swift 3: 2 "".count // 1, in Swift 3: 2 "".count // 1, in Swift 3: 2 - person + skin tone "".count // 1, in Swift 3: 4 "".count // 3, in Swift 3: 1

Alle oben genannten Änderungen und implementierten Vorschläge (wie viele andere) haben ihre Wurzeln in einem breit beschriebenen Satz von Funktionen, dem String-Manifest.

Zugangskontrolle

Swift 3 brachte ein sehr widersprüchliches Element in die Zugriffskontrolle - den fileprivate Zugriffsmodifizierer, der wirklich verwirrend sein kann.
Zuvor wurde der Modifikator private Zugriffsebene verwendet, um Typmember vor anderen Typen auszublenden, und auf private Member konnte nur über Methoden und Eigenschaften zugegriffen werden, die bei der Typdefinition definiert wurden, wobei die gleichen Typerweiterungen beiseite gelassen wurden, da sie nicht auf diese Member zugreifen konnten.
fileprivate könnte verwendet werden, um den Zugriff für fileprivate wie Eigenschaften und Methoden innerhalb derselben Datei gemeinsam zu nutzen.
Tatsächlich führte die Verwendung von private zu einem Problem, wenn Erweiterungen eines Typs keinen Zugriff auf Mitglieder dieses Typs hatten. fileprivate Verwendung von fileprivate unter solchen Umständen eine sehr gängige Lösung, was zu einem anderen Problem geführt hat: dieselbe Datei könnte auch auf diese Mitglieder zugreifen.

Swift 4 bringt Ordnung, indem es Erweiterungen des Typs erlaubt, auf private Member dieses Typs in derselben Datei zuzugreifen, wie in SE-0169 beschrieben:

 struct User { private let firstName: String private let lastName: String } extension User: CustomStringConvertible { var description: String { return "User: \(firstName) \(lastName)" } }

Wörterbuch und Set

Dictionary mit Sequence initialisieren

Dictionary kann jetzt mit Sequence initialisiert werden, aber nicht alle Sequenzen konnten in diesem Initialisierer übergeben werden, nur diejenigen, die Tupel enthalten (Key, Value) , wobei Key der Schlüsseltyp des Dictionary und Value der Dictionary-Werttyp ist:

 let stocksIdentifiers = ["AAPL", "GOOGL", "NKE"] let stocksValues = [158.28, 940.13, 53.73] let pairs = zip(stocksIdentifiers, stocksValues) let stocksValuesDict = Dictionary(uniqueKeysWithValues: pairs) // ["GOOGL": 940.13, "NKE": 53.73, "AAPL": 158.28]

Hier erstellt die zip Funktion ein Paar ( Tuple s) aus 2 Sequenzen, Sie können mehr über diese Funktion in der Dokumentation der Swift Standard Library lesen.

Wörterbücher zusammenführen

Sie können festlegen , wie doppelte Schlüssel gehandhabt werden soll , wenn ein Wörterbuch aus einer Folge der Schaffung Tuple s durch einen Verschluss vorbei uniquingKeysWith Parameter, die Werte zu kombinieren aus 2 identischen Schlüsseln verwendet wird.

Beispiel 1:

 let duplicates = [("a", 1), ("b", 5), ("a", 3), ("b", 3)] let dictionary = Dictionary(duplicates, uniquingKeysWith: { (first, _) in return first }) // ["b": 5, "a": 1]

Hier lassen wir den ersten Wert und ignorieren alle nächsten Werte mit demselben Schlüssel.

Beispiel 2:

Zählen, wie oft jedes Zeichen in einer Zeichenfolge vorkommt.

 let string = "Hello!" let pairs = Array(zip(string, repeatElement(1, count: string.count))) let counts = Dictionary(pairs, uniquingKeysWith: +) // ["H": 1, "e": 1, "o": 1, "l": 2, "!": 1]

Beispiel 3:

Verwenden der merge :

 let values = ["a": 1, "b": 5] var additionalValues = ["b": 3, "c": 2, "a": 3] additionalValues.merge(values, uniquingKeysWith: +) // ["b": 8, "c": 2, "a": 4]

Tiefgestellt mit Standardwert

Bisher war es üblich, den Koaleszenzoperator nil zu verwenden, um einen Standardwert anzugeben, falls der Wert nil ist.

Schnell 3:

 let dict = ["a": 1, "b": 5] dict["c"] ?? 0 // 0

Swift 4 führt einen neuen default für tiefgestellte Zeichen ein (Teil von SE-0165):

 let dict = ["a": 1, "b": 5] dict["c", default: 0] // 0, equals to `dict["c"] ?? 0` in Swift 3

Sie können ein Wörterbuch auch mutieren, während Sie es mit dem Standardwert abonnieren:

 let string = """ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam mattis lorem et leo laoreet fermentum. Mauris pretium enim ac mi tempor viverra et fermentum nisl. Sed diam nibh, posuere non lectus at, ornare bibendum erat. Fusce mattis sem ac feugiat vulputate. Morbi at nunc maximus, vestibulum orci et, dictum neque. Vestibulum vulputate augue ac libero vulputate vestibulum. Nullam blandit et sapien non fermentum. Proin mollis nisl at vulputate euismod. """ var wordsCountByLine = [Int: Int]() let lines = string.split(separator: "\n") for (index, line) in lines.enumerated() { let lineWordsCount = line.split(separator: " ").count wordsCountByLine[index, default: 0] += lineWordsCount } print(wordsCountByLine) // [2: 10, 4: 15, 5: 7, 6: 6, 7: 6, 0: 8, 1: 7, 3: 10]

Wörterbuchspezifische Karte und Filter

Gruppieren von Sequenzelementen

Eingeschränkte assoziierte Typen in Protokollen

Vorschlag SE-0142 führt das Hinzufügen von Bedingungsklauseln zu zugeordneten Typdeklarationen ein.

 extension Sequence where Element: Numeric { var sum: Element { var result: Element = 0 for element in self { result += element } return result } } [1,2,3,4].sum

Archivierung & Serialisierung (Kodierung / Dekodierung)

Zuvor mussten Sie zum Serialisieren eines benutzerdefinierten Typs das alte und bekannte NSCoding Protokoll verwenden. Das Problem ist, dass Nicht-Klassen-Typen wie struct und enum dieses Protokoll nicht enum können, sodass Entwickler nichts anderes tun mussten, als Hacks zu verwenden, wie zum Beispiel eine zusätzliche Ebene der Kompatibilität NSCoding indem sie eine verschachtelte Klasse erstellen, die NSCoding entsprechen NSCoding .

Swift 4 hat dank SE-0166 eine sehr bequeme Lösung für dieses Problem - eine Einführung des Codable Protokolls:

 struct Employee: Codable { let name: String let age: Int let role: Role enum Role: String, Codable { case manager case developer case admin } } struct Company { let name: String let officeLocation: Location? let employees: [Employee] } struct Location : Codable { let latitude: Double let longitude: Double }

In einem einfachen Fall wie diesem müssen Sie nur alle Ihre benutzerdefinierten Typen mit der Codable Protokollkonformität versehen. Der Compiler Codable die ganze Magie für Sie. Das ist es!

Codable ist ein typealias für eine Zusammenstellung von Decodable und Encodable Protokollen, sodass Sie beispielsweise nur die Decodable des Decodable Protokolls deklarieren können, wenn Sie Ihre Decodable aus JSON-Daten decodieren möchten.

Codierung

Wenn Sie einen Codable Wert serialisieren oder deserialisieren Codable , müssen Sie ein Codable oder Codable verwenden. Swift 4 enthält bereits eine Reihe von Encodern/Decodern für JSON und Eigenschaftslisten sowie neue CocoaError s für verschiedene Arten von Fehlern, die während der Kodierung/Dekodierung ausgelöst werden könnten. NSKeyedArchiver und NSKeyedUnarchiver unterstützen auch Codable Typen.

 let employee = Employee(name: "Peter", age: 27, role: .manager) let company = Company(name: "Awesome Company", officeLocation: nil, employees: [employee]) let encoder = JSONEncoder() let companyData = try encoder.encode(company) let string = String(data: companyData, encoding: .utf8)! print(string) >>> { "name" : "Awesome Company", "employees" : [ { "name" : "Peter", "age" : 27, "role" : "manager" } ] }

Ein Stück Kuchen, nicht wahr?

Dekodierung

Decoder wird verwendet, um den benutzerdefinierten Codable Typ aus Data zu deserialisieren. Es weiß nicht, welcher Typ aus den Daten selbst dekodiert werden soll, daher sollten Sie angeben, welcher Typ dekodiert werden soll, zum Beispiel Employee oder [Employee] :

 let decoder = JSONDecoder() let jsonData = """ [ { "name" : "Peter", "age" : 27, "role" : "manager" }, { "name" : "Alex", "age" : 26, "role" : "developer" }, { "name" : "Eugene", "age" : 30, "role" : "admin" } ] """.data(using: .utf8)! let employees = try decoder.decode([Employee].self, from: jsonData)
 If one of `Codable` type instances fails to decode, then whole collection will fail to decode.

Benutzerdefinierte Schlüsselnamen

In den meisten Fällen stimmen Namen, die wir in benutzerdefinierten Swift-Typen verwenden, nicht mit den Schlüsseln in JSON-Daten überein, die diesen Typ darstellen. Um eine Zuordnung zwischen benutzerdefinierten CodingKeys und JSON-Schlüsseln zu erstellen, können Sie eine verschachtelte CodingKeys namens CodingKeys die dem CodingKey Protokoll entsprechen sollte:

 struct Country: Decodable { let id: String let name: String let phoneCode: String private enum CodingKeys: String, CodingKey { case id = "alpha3" case name case phoneCode = "phone_code" } }

Benutzerdefinierte Dekodierung

Wenn Sie einen komplexen Fall haben, können Sie Ihren benutzerdefinierten Initialisierer aus einem Decodable Protokoll Decodable :

 struct Transaction { let id: Int let action: String let source: String let amount: Int let state: TransactionState let createdAt: Date let authorName: String enum TransactionState: String, Decodable { case done case canceled case processed } } extension Transaction: Decodable { private enum CodingKeys: String, CodingKey { case id case action = "action_name" case source = "source_name" case amount case state case createdAt = "created_at" case author } private enum AuthorKeys: String, CodingKey { case fullName = "full_name" } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) id = try container.decode(Int.self, forKey: .id) actionName = try container.decode(String.self, forKey: .action) sourceName = try container.decode(String.self, forKey: .source) let createdAtValue = try container.decode(Double.self, forKey: .createdAt) createdAt = Date(timeIntervalSince1970: createdAtValue) state = try container.decode(TransactionState.self, forKey: .state) amount = try container.decodeIfPresent(Int.self, forKey: .amount) ?? 0 do { let authorContainer = try container.nestedContainer(keyedBy: AuthorKeys.self, forKey: .author) authorName = try authorContainer.decode(String.self, forKey: .fullName) } catch { authorName = "" } } }

Schlüsselwert-Codierung

Eine der praktischen Funktionen von Swift 4 sind Smart KeyPaths, die in SE-0161 beschrieben werden. Im Gegensatz zu Swift 3 #keyPath() , das nicht stark typisiert ist und nur für Objective-C-Mitglieder funktioniert, ist Swift 4 KeyPath eine generische Klasse, was bedeutet, dass Schlüsselpfade jetzt stark typisiert sind. Lassen Sie uns in einige Beispiele eintauchen:

 struct User { var username: String }

Die allgemeine Form des Schlüsselpfads \<Type>.<path> , wobei <Type> ein \User.username ist und <path> eine Kette einer oder mehrerer Eigenschaften ist, z. B. \User.username :

 let user = User(username: "max") let username = user[keyPath: \User.username] // "max"

Sie können auch einen neuen Wert mit diesem Schlüsselpfad schreiben, wenn er veränderbar ist:

 var user = User(username: "max") user[keyPath: \User.username] = "alex" // "alex"

Schlüsselpfade sind nicht auf eine Hierarchieebene beschränkt:

 struct Comment { let content: String var author: User } let max = User(username: "max") let comment = Comment(content: "Nice post!", author: max) let authorUsername = comment[keyPath: \Comment.author.username] // "max"

Schlüsselpfade können in einer Variablen gespeichert werden:

 let authorKeyPath = \Comment.author let usernameKeyPath = authorKeyPath.appending(path: \.username) let authorUsername = comment[keyPath: usernameKeyPath] // "max"

Sie können auch Schlüsselpfade für optionale und berechnete Eigenschaften verwenden:

 struct Post { let title: String var comments: [Comment] var topComment: Comment? { return comments.first } } let max = User(username: "max") let alex = User(username: "alex") var post = Post(title: "What's new in Swift 4", comments: []) let topCommentAuthorUsernameKeyPath = \Post.topComment?.author.username post[keyPath: topCommentAuthorUsernameKeyPath] // nil let comment = Comment(content: "", author: alex) let anotherComment = Comment(content: "Nice post!", author: max) post.comments = [comment, anotherComment] post[keyPath: topCommentAuthorUsernameKeyPath] // "alex"

Obwohl die Highlights von SE-0161 Indizes in Schlüsselpfaden unterstützen, wurden sie noch nicht implementiert:

 post.comments[keyPath: \.[0].content] // error: key path support for subscript components is not implemented let firstCommentAuthorKeyPath = \Post.comments[0].author // error: key path support for subscript components is not implemented

KVO

Neben neuen Schlüsselpfaden wurde auch die API zur Beobachtung von Schlüsselwerten in Swift 4 aktualisiert.

 New KVO APIs depend on Objective-C runtime and works for `NSObject` subclasses only, so it can't be used for Swift structs and classes which don't inherit `NSObject`. In order to observe property it should be marked as `@objc dynamic var`.
 class User: NSObject { @objc dynamic var name: String var username: String init(name: String, username: String) { self.name = name self.userName = userName super.init() } } let user = User(name: "Max", username: "max") let nameObservation = user.observe(\.name, options: [.new, .old]) { user, change in // NSKeyValueObservation if let oldValue = change.oldValue, let newValue = change.newValue { print("fullName has changed from \(oldValue) to \(newValue)") } else { print("fullName is now \(user.name)") } } user.name = "Alex" // name has changed from Max to Alex

Rufen Sie die Methode invalidate() , wenn Sie die Beobachtung stoppen möchten

 nameObservation.invalidate() user.name = "Elina" // observer isn't get called

Es wird auch gestoppt, wenn es Deinitiert wird, also stelle sicher, dass du es im Eigentum oder woanders lagerst, wenn du es bewahren möchtest.

Einseitige Bereiche

SE-0172 führt "einseitige" Bereiche ein, die über Präfix-/Postfix-Versionen der bestehenden Bereichsoperatoren erstellt werden, und ein neues RangeExpression Protokoll, um die Erstellung von Methoden zu vereinfachen, die verschiedene Arten von Bereichen verwenden.

Unendliche Sequenzen

Sie können einen einseitigen Bereich verwenden, um eine unendliche Folge zu konstruieren:

 let letters = ["a", "b", "c", "d"] let numberedLetters = Array(zip(1..., letters)) // [(1, "a"), (2, "b"), (3, "c"), (4, "d")]
 let string = "Hello, Mind Studios!" let index = string.index(of: ",")! string[..<index] // "Hello" string[...index] // "Hello,"

Verwenden von einseitigen Bereichen beim Musterabgleich

 let value = 5 switch value { case 1...: print("greater than zero") case 0: print("zero") case ..<0: print("less than zero") default: break }

Generische Tiefstellungen

SE-0148 Indizes können jetzt generische Argumente und Rückgabetypen haben

 struct JSON { let data: [String: Any] subscript<T>(key: String) -> T? { return data[key] as? T } } let jsonDictionary: [String: Any] = [ "name": "Ukraine", "flag": "", "population": 42_500_000 ] let json = JSON(data: jsonDictionary) let population: Int? = json["population"] // 42500600
 extension Dictionary where Value == String { subscript<T: RawRepresentable>(key: Key) -> T? where T.RawValue == Value { guard let string = self[key] else { return nil } return T(rawValue: string) } } enum Color: String { case red case green case blue } let dictionary = [1: "red"] let color: Color? = dictionary[1] // red

Begrenzende Objective-C-Inferenz

Swift 4 minimiert die @objc-Inferenz, indem es auf die Fälle beschränkt wird, in denen die Deklaration für Objective-C verfügbar sein muss (SE-0160).
Dies verringert die Binärgröße Ihrer App, indem kein redundanter Objective-C-Code kompiliert wird, wenn Sie ihn nicht verwenden, und gibt mehr Kontrolle darüber, wann @objc abgeleitet wird. Von NSObject abgeleitete Klassen leiten @objc nicht mehr ab.

Es gibt jedoch einige Situationen, in denen Swift-Code weiterhin eine implizite Schlussfolgerung hat:

  • Deklarationen mit einem @objc-Attribut

  • Deklarationen, die eine Anforderung eines @objc-Protokolls erfüllen

  • Deklarationen mit @IBAction-, @IBInspectable-, @IBOutlet-, @NSManaged-, @GKInspectable-Attributen

Um die @objc-Inferenz für eine ganze Klasse zu aktivieren, können Sie das neue @objcmembers-Attribut verwenden.
Um die @objc-Inferenz für eine bestimmte Erweiterung oder Funktion zu deaktivieren, fügen Sie das neue @nonobjc-Attribut hinzu.

Verfassen von Klassen und Protokollen

In Swift 4 können wir jetzt Protokolle zusammen mit anderen Swift-Typen erstellen:

 User & Codable & CustomStringConvertible typealias MyType = User & Codable & CustomStringConvertible

Vorteile von Swift 4.

Die Vorteile von Swift 4 sind wirklich riesig, wie es oft passiert, wenn Apple eine neue Sprachversion veröffentlicht. Abgesehen von der verbesserten Sprachleistung hat es auch den Migrationsprozess stark stabilisiert. Wenn wir uns wieder auf den Prozess der Migration von Swift 2.2 auf 3.0 konzentrieren, erinnern wir uns an den komplizierten Prozess der Übertragung aller Abhängigkeiten. Swift 4.0-Änderungen ermöglichen es uns, die Bibliotheken von Drittanbietern zu verlassen, ohne sie tatsächlich zu „verlagern“ – Sie müssen nur Swift selbst aktualisieren.

Auch in Bezug auf die Verbesserungen von Swift 4.0 vs. 3.0 wurde die Größe der kompilierten Binärdateien geändert, was zu einer Verringerung der App-Größe geführt hat. zB die mobile Anwendung wog bisher 20 MB, in der neusten Swift-Version etwa 17 MB. Und es gibt einen grundlegenden Unterschied zwischen Swift 4 und Swift 3 - die Fehlerbehebung ist erfolgt und die Sprache ist etwas schneller geworden.

Es ist Jahre her, dass Swift im Einsatz war, und es entwickelt sich mit jedem kommenden Update weiter. Mit jeder neuen Sprache erneuern sich neue Entwicklungsperspektiven, die bisher unbekannt waren, und wir freuen uns darauf, neue iOS-Horizonte zu erkunden.

Verpassen Sie nicht unseren Artikel über MVP vs. MVC vs. MVVM vs. VIPER für die iOS-Entwicklung.

Geschrieben von Max Mashkov und Elina Bessarabova .