Swift 4.0 vs Swift 3.0 - Différences et nouvelles fonctionnalités

Publié: 2021-10-05

Le jour où Apple sort une nouvelle version du célèbre langage Swift nous a enfin frappé. Que doit-on en attendre ? En tremblant d'impatience, nous avons décidé de vous présenter un petit aperçu des nouvelles mises à jour qui seront présentes dans la version Swift 4 .

3 Les pierres angulaires de Swift.

En tant que langage fantastique pour écrire du code, Swift a ses propres avantages et est censé « survivre » au langage Objective-C.

Vous êtes invités à lire les principales différences entre Swift et Objective-C

Swift est rapide , typé et très expressif . Il pourrait être utilisé pour écrire des logiciels sur des téléphones et des tablettes, des ordinateurs de bureau et des serveurs - apparemment, sur tout ce qui exécute du code. Il vous invite à jouer avec - avec l'application d'apprentissage du codage Swift Playgrounds d'Apple ou en utilisant Playgrounds dans Xcode, vous pouvez voir les résultats de votre travail immédiatement, pas besoin de mettre le nez dans le développement et l'exécution d'une application à première place. Avec chaque nouvelle version additive, cela devient meilleur et plus rapide, et c'est le cas avec la version Swift 4.
Prêt-stable ?

Une autre fonctionnalité intéressante que Xcode 9 possède pour Swift 4 - vous n'avez pas à vous soucier beaucoup de la migration à venir et vous comprendrez pourquoi en lisant cet article.

En parlant de cela, explorons brièvement ce que les bonbons et les nouvelles fonctionnalités de Swift 4 nous apportent cet automne.

Commencer

Le langage lui-même n'est pas très utile sans un IDE pratique, qui est Xcode dans le monde des développeurs. Vous pouvez télécharger la dernière version de Xcode 9 sur le Mac App Store ou sur la page Téléchargements du site Apple Developer, mais assurez-vous d'abord que vous disposez d'un compte développeur actif. Il est assez stable, vous pouvez donc remplacer Xcode 8 par celui-ci pour vos routines de codage quotidiennes.

Vous pouvez également installer plusieurs versions de Xcode en utilisant xcversion

Si vous démarrez un nouveau projet, vous êtes prêt à partir. Mais si vous avez déjà un projet écrit en Swift 3.x, vous devez passer par un processus de migration.

Nous vous recommandons d'essayer d'abord sur le Playground - pour vous habituer aux nouvelles fonctionnalités.

Vous remarquerez des liens vers les propositions Swift Evolution au format « SE-____ » pendant que vous lisez cet article.

Migration vers Swift 4

La migration d'une version majeure de Swift à la suivante a toujours été assez intense, en particulier de Swift 2.x à 3.0. Cela prend généralement environ 1 à 2 jours par projet, mais la migration vers Swift 4 est un peu plus facile et peut être effectuée beaucoup plus rapidement.

Préparation pré-migration

Xcode 9 prend en charge non seulement Swift 4, mais également une version de transition 3.2, de sorte que votre projet devrait être compilé sans aucune difficulté. Cela est possible car le compilateur et l'outil de migration Swift 4 prennent en charge les deux versions du langage. Vous pouvez spécifier différentes versions de Swift par cible, cela est très utile si certaines bibliothèques tierces n'ont pas encore été mises à jour ou si vous avez plusieurs cibles dans votre projet. Cependant, pas seulement la langue, mais le SDK a également subi quelques modifications, il est donc très probable que certaines mises à jour devront être appliquées à votre code car Apple continue de mettre à jour les API du SDK...

Outil de migration rapide

Comme toujours, Apple fournit un outil de migration Swift intégré à Xcode qui peut aider à migrer à partir de la version précédente de Swift. Vous pouvez le lancer dans Xcode en allant dans Edition -> Convertir -> Vers la syntaxe Swift actuelle… et en sélectionnant les cibles que vous souhaitez convertir.

Il vous sera ensuite demandé quelle préférence d'inférence Objective-C vous souhaitez appliquer :

Comme les changements additifs dominent dans Swift 4, l'outil de migration Swift gérera la plupart des changements pour vous.

CocoaPods

La plupart des développeurs de  utilisent le gestionnaire de dépendances CocoaPods pour leurs projets, car Swift Package Manager n'est pas aussi mature qu'il pourrait l'être, bien qu'il s'améliore très rapidement. Comme mentionné ci-dessus, toutes les bibliothèques tierces n'ont pas encore été mises à jour vers Swift 4, vous pouvez donc voir des erreurs lors de la compilation de certaines d'entre elles. Une solution possible pour résoudre ce problème consiste à spécifier Swift version 3.2 pour les pods qui n'ont pas encore été mis à jour en ajoutant un script post_install à votre 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

Puis cours

 pod install

Vous pouvez désormais compiler des pods sans erreur.

Examinons les modifications et ajouts apportés à l'API Swift 4.

Modifications et ajouts d'API

Cordes

String est désormais conforme au protocole Collection grâce à la proposition SE-0163. Vous vous souvenez de Swift 1.x ?

La propriété de tableau de characters n'est plus nécessaire maintenant, car vous pouvez itérer directement sur String :

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

Cela signifie également que vous pouvez utiliser n'importe quelle méthode et propriété Collection sur String , comme count , isEmpty , map() , filter() , index(of:) et bien d'autres :

 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"

Nouveau type de Substring - Substring

Swift 4 apporte un nouveau type Substring qui représente une sous-séquence de String (comme décrit dans SE-0163 mentionné ci-dessus).

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

String et Substring désormais en charge le nouveau StringProtocol qui les rend presque identiques et interopérables :

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

Note importante

SE-0163 a une note très importante :

 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.

Ce qui signifie que Substring est destiné à être utilisé comme stockage temporaire pour la sous-séquence String . Si vous souhaitez le transmettre à certaines méthodes ou à d'autres classes, convertissez-le d'abord en String :

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

Quoi qu'il en soit, le système de types de Swift vous aidera à ne pas passer Substring quelque part où String est attendu (en supposant que vous n'utilisez pas le nouveau StringProtocol comme type de paramètre).

Littéraux de chaîne multiligne

SE-0168 introduit une syntaxe simple pour les littéraux de chaînes multilignes utilisant trois guillemets """ ce qui signifie que la plupart des formats de texte (tels que JSON ou HTML) ou du texte long peuvent être collés sans échappement :

 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. """

Échapper aux nouvelles lignes dans les littéraux de chaîne

SE-0182 ajoute la possibilité d'échapper aux retours à la ligne dans les littéraux de chaîne multiligne avec une barre oblique inverse à la fin de la ligne.

 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

Prise en charge améliorée d'Unicode

Swift 4 prend en charge Unicode 9, ce qui signifie que les problèmes de comptage des caractères Unicode sont désormais résolus :

 "".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

Tous les changements et propositions mis en œuvre mis en évidence ci-dessus (comme beaucoup d'autres) tirent leurs racines d'un ensemble de fonctionnalités largement décrit appelé String Manifesto.

Contrôle d'accès

Swift 3 a apporté un élément très contradictoire au contrôle d'accès - un modificateur d'accès fileprivate qui peut être vraiment déroutant.
Auparavant, private modificateur de niveau d'accès private était utilisé pour masquer les membres de type des autres types et les membres privés n'étaient accessibles que par les méthodes et les propriétés définies lors de la définition du type, laissant les mêmes extensions de type de côté car ils ne pouvaient pas accéder à ces membres.
fileprivate peut être utilisé pour partager l'accès pour les membres de type, tels que les propriétés et les méthodes, dans le même fichier.
En fait, l'utilisation de private conduit à un problème lorsque les extensions d'un certain type n'avaient pas accès aux membres de ce type, donc utiliser fileprivate dans de telles circonstances était une solution très courante, ce qui a conduit à un autre problème : d'autres types dans le même fichier pourrait également accéder à ces membres.

Swift 4 met les choses en ordre en permettant aux extensions sur le type d'accéder private membres private de ce type dans le même fichier comme décrit dans SE-0169 :

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

Dictionnaire et ensemble

Initialisation du Dictionary avec la Sequence

Dictionary peut être initialisé avec Sequence maintenant, mais toutes les séquences ne peuvent pas être passées dans cet initialiseur, uniquement celles contenant des tuples (Key, Value) , où Key est le type de clé du Dictionary et Value représente le type de valeur du Dictionary :

 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]

Ici, la fonction zip crée une paire ( Tuple s) à partir de 2 séquences, vous pouvez en savoir plus sur cette fonction dans la documentation Swift Standard Library.

Fusion de dictionnaires

Vous pouvez spécifier comment les clés en double doivent être gérées lors de la création d'un dictionnaire à partir d'une séquence de Tuple en passant une fermeture au paramètre uniquingKeysWith , qui est utilisé pour combiner les valeurs de 2 clés identiques.

Exemple 1:

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

Ici, nous laissons la première valeur en ignorant toutes les valeurs suivantes avec la même clé.

Exemple 2 :

Compter combien de fois chaque caractère apparaît dans la chaîne.

 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]

Exemple 3 :

Utilisation de la méthode de 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]

Indice avec valeur par défaut

Auparavant, une pratique courante consistait à utiliser l'opérateur de coalescence nil pour donner une valeur par défaut au cas où la valeur serait nulle.

Rapide 3 :

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

Swift 4 introduit une nouvelle valeur default sur les indices (faisant partie de SE-0165) :

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

Vous pouvez également muter un dictionnaire en l'inscrivant avec la valeur par défaut :

 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]

Carte et filtre spécifiques au dictionnaire

Regroupement d'éléments de séquence

Types associés contraints dans les protocoles

La proposition SE-0142 introduit l'ajout de clauses conditionnelles aux déclarations de type associées.

 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

Archivage & Sérialisation (Encodage / Décodage)

Auparavant, pour sérialiser un type personnalisé, vous deviez utiliser NSCoding protocole NSCoding ancien et bien connu. Le problème est que les types non-classe tels que struct et enum ne peuvent pas se conformer à ce protocole, donc les développeurs n'avaient rien à faire que d'utiliser des hacks comme fournir une couche supplémentaire de compatibilité en créant une classe imbriquée qui pourrait se conformer à NSCoding .

Swift 4 a une solution très pratique à ce problème grâce à SE-0166 - une introduction du protocole Codable :

 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 }

Dans un cas simple comme celui-ci, tout ce dont vous avez besoin est d'ajouter la Codable protocole Codable à tous vos types personnalisés, le compilateur fera toute la magie pour vous. C'est ça!

Codable est un typealias de typealias pour une composition de protocoles Decodable & Encodable , vous pouvez donc déclarer, par exemple, uniquement la Decodable protocole Decodable si vous souhaitez décoder votre instance de type à partir de données JSON.

Codage

Si vous souhaitez sérialiser ou désérialiser une valeur Codable , vous devez utiliser un objet encodeur ou décodeur. Swift 4 est déjà livré avec un ensemble d'encodeurs/décodeurs pour JSON et des listes de propriétés, ainsi que de nouvelles CocoaError pour différents types d'erreurs qui pourraient être générées lors de l'encodage/décodage. NSKeyedArchiver et NSKeyedUnarchiver également en charge les types Codable .

 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" } ] }

Un morceau de gâteau, n'est-ce pas ?

Décodage

Decoder est utilisé pour désérialiser le type Codable personnalisé à partir de Data . Il ne sait pas quel type décoder à partir des données elles-mêmes, vous devez donc spécifier quel type décoder, par exemple, Employee ou [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.

Noms de clé personnalisés

Dans la plupart des cas, les noms que nous utilisons dans les types Swift personnalisés ne correspondent pas aux clés des données JSON qui représentent ce type. Pour créer un mappage entre les noms de propriétés de type personnalisé et les clés JSON, vous pouvez créer une énumération imbriquée nommée CodingKeys qui doit être conforme au protocole CodingKey :

 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" } }

Décodage personnalisé

Si vous avez un cas complexe, vous pouvez implémenter votre initialiseur personnalisé à partir d'un protocole 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 = "" } } }

Codage de la valeur clé

L'une des fonctionnalités pratiques de Swift 4 est les Smart KeyPaths décrits dans SE-0161. Contrairement à Swift 3 #keyPath() , qui n'est pas fortement typé et ne fonctionne que pour les membres Objective-C, Swift 4 KeyPath est une classe générique, ce qui signifie que les chemins de clé sont désormais fortement typés. Plongeons dans quelques exemples :

 struct User { var username: String }

La forme générale du chemin de clé \<Type>.<path> , où <Type> est un nom de type et <path> est une chaîne d'une ou plusieurs propriétés, par exemple, \User.username :

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

Vous pouvez également écrire une nouvelle valeur par ce chemin de clé s'il est mutable :

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

Les chemins clés ne sont pas limités à un seul niveau de hiérarchie :

 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"

Les chemins des clés peuvent être stockés dans une variable :

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

Vous pouvez également utiliser des chemins de clé pour les propriétés facultatives et calculées :

 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"

Malgré le fait que SE-0161 met en évidence les indices de prise en charge dans les chemins clés, ils n'ont pas encore été implémentés :

 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

En plus des nouveaux chemins de clé, l'API d'observation de la valeur-clé a également été mise à jour dans Swift 4.

 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

Appelez la méthode invalidate() si vous souhaitez arrêter l'observation

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

Il est également arrêté lorsqu'il est défini, alors assurez-vous de le stocker dans la propriété ou ailleurs si vous souhaitez le conserver.

Gammes unilatérales

SE-0172 introduit des plages "unilatérales", créées via des versions préfixe/postfixe des opérateurs de plage existants, et un nouveau protocole RangeExpression pour simplifier la création de méthodes qui prennent différents types de plages.

Séquences infinies

Vous pouvez utiliser une plage unilatérale pour construire une séquence infinie :

 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,"

Utilisation de plages unilatérales dans la correspondance de motifs

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

Indices génériques

SE-0148 Les indices peuvent désormais avoir des arguments génériques et des types de retour

 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

Limitation de l'inférence Objective-C

Swift 4 minimise l'inférence @objc en la limitant aux seuls cas où la déclaration doit être disponible pour Objective-C (SE-0160).
Cela réduit la taille binaire de votre application en ne compilant pas de code Objective-C redondant si vous ne l'utilisez pas, et donne plus de contrôle sur le moment où @objc sera déduit. Les classes dérivées de NSObject n'infèrent plus @objc.

Mais il existe certaines situations dans lesquelles le code Swift continuera à avoir une inférence implicite :

  • Déclarations qui ont un attribut @objc

  • Déclarations qui satisfont à une exigence d'un protocole @objc

  • Déclarations ayant les attributs @IBAction, @IBInspectable, @IBOutlet, @NSManaged, @GKInspectable

Pour activer l'inférence @objc pour une classe entière, vous pouvez utiliser le nouvel attribut @objcmembers.
Pour désactiver l'inférence @objc pour une extension ou une fonction spécifique, ajoutez le nouvel attribut @nonobjc.

Composer des cours et des protocoles

Dans Swift 4, nous pouvons désormais composer des protocoles avec d'autres types de Swift :

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

Avantages de Swift 4.

Les avantages de Swift 4 sont vraiment énormes, comme cela arrive souvent lorsqu'Apple sort une nouvelle version linguistique. Outre l'amélioration des performances linguistiques, il a également considérablement stabilisé le processus de migration. En repensant au processus de migration de Swift 2.2 vers 3.0, nous rappelons le processus perplexe de transfert de toutes les dépendances. Les modifications de Swift 4.0 nous permettent de quitter les bibliothèques tierces sans réellement les "déplacer" - il vous suffit de mettre à jour Swift lui-même.

Concernant également les améliorations de Swift 4.0 vs 3.0, la taille des fichiers binaires compilés a été modifiée, ce qui a entraîné une diminution de la taille de l'application ; par exemple, l'application mobile pesait 20 Mo, et dans la dernière version de Swift, cela prendra environ 17 Mo. Et il y a une différence fondamentale entre Swift 4 et Swift 3 - la correction du bogue a eu lieu et le langage est devenu un peu plus rapide.

Cela fait des années que Swift est utilisé et il continue d'évoluer avec chaque mise à jour à venir. Avec chaque nouvelle langue, de nouvelles perspectives de développement, inconnues auparavant, se présentent et nous sommes impatients d'explorer de nouveaux horizons iOS.

Ne manquez pas notre article sur MVP vs MVC vs MVVM vs VIPER pour le développement iOS.

Écrit par Max Mashkov et Elina Bessarabova .