Cette semaine s’est déroulé la WWDC, la grande messe d’Apple pour ses développeurs. Ça a été l’occasion de présenter tout un tas de nouveauté et/ou évolution de leur écosystème logiciel comme macOS Serria, iOS 10, tvOS 10 ou watchOS 3. Ils ont également présenté la nouvelle version de leur IDE, XCode 8, qui intègre par défaut la dernière version du langage Swift ! Il y a beaucoup de changement entre Swift 3 et Swift 2.2, et vous devrez probablement modifier votre ancien code pour qu’il compile avec cette nouvelle version. Nous allons donc lister les principaux changements ici.
Changement des APIs
Commençons par les plus grands changements apportés par cette nouvelle version de Swift : la « Swiftification » des APIs. En effet Apple a publié des lignes directrices pour l’écriture des APIs visant à simplifier la lecture du code, l’apprentissage de Swift et surtout à harmoniser leurs conceptions.
Tous les paramètres de fonction sont étiquetés par défaut
Jusqu’à Swift 2.2 lorsque l’on appelait une fonction ou une méthode on omettait l’étiquette du premier paramètre. Afin de maintenir une cohérence, la proposition SE-0046 harmonise tous ça ! Voici un example simple :
func ditBonjour(nom: String, prénom: String) {
print("Bonjour \(nom) \(prénom) !")
}
// Swift 2.2
ditBonjour("Swift", prénom: "Tuto")
// Swift 3
ditBonjour(nom: "Swift", prénom: "Tuto")
Cela a pour effet de modifier la signature de la plupart des APIs de Cocoa afin d’éviter les répétitions :
// Swift 2, suivi par Swift 3
names.indexOf("Taylor")
names.index(of: "Taylor")
"Taylor".writeToFile("filename", atomically: true, encoding: NSUTF8StringEncoding)
"Taylor".write(toFile: "filename", atomically: true, encoding: NSUTF8StringEncoding)
SKAction.rotateByAngle(CGFloat(M_PI_2), duration: 10)
SKAction.rotate(byAngle: CGFloat(M_PI_2), duration: 10)
UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline)
UIFont.preferredFont(forTextStyle: UIFontTextStyleSubheadline)
func numberOfSectionsInTableView(tableView: UITableView) -> Int
func numberOfSections(in tableView: UITableView) -> Int
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView?
func viewForZooming(in scrollView: UIScrollView) -> UIView?
Vous noterez que la définition des méthodes utilise des préposition comme of
, to
, with
, in
comme étiquette externe. Ces changements ont pour but d’optimiser la lisibilité du code.
Si l’appel de méthode se lit correctement sans préposition et n’a pas besoin d’étiquette on peut toujours exclure ce label en utilisant l’underscore comme dans Swift 2.2 :
func viewWillAppear(_ animated: Bool)
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
func textFieldShouldReturn(_ textField: UITextField) -> Bool
Omettre les mots inutiles
Swift n’est pas une évolution de l’Objective-C, mais un remplacement. Cependant il a gardé jusqu’à maintenant ses conventions de nommage, dont l’une d’entre elle était d’indiquer le paramètre de retour. Comme Swift est un langage typé et profite de la vérification de type de son compilateur ces conventions ne sont plus utile. Au contraire l’équipe derrière Swift estimait que cela compliquait la lecture du code (proposition SE-0005) ! Voici quelques changement que Swit 3 apporte :
// Swift 2, suivi par Swift 3
let blue = UIColor.blueColor()
let blue = UIColor.blue()
let min = numbers.minElement()
let min = numbers.min()
attributedString.appendAttributedString("...")
attributedString.append("...")
names.insert("Swift", atIndex: 0)
names.insert("Swift", at: 0)
UIDevice.currentDevice()
UIDevice.current()
Utilisation du lowerCamelCase pour les énumérations et les propriétés
La proposition SE-0006 a introduit l’utilisation du lowerCamelCase au lieu de l’UpperCamelCase pour les énumérations et les propriétés :
// Swift 2, suivi par Swift 3
let uneURL = NSURLRequest(URL: "http://...")
let uneURL = NSURLRequest(url: "http://...")
let rouge = UIColor.red().CGColor
let rouge = UIColor.red().cgColor
UIInterfaceOrientationMask.Portrait
UIInterfaceOrientationMask.portrait
for case let .Some(nom) in noms {}
for case let .some(nom) in noms {}
Les verbes et les noms
Swift 3 souhaite également obtenir plus de cohérence dans la nommage de méthode utilisant des verbes et des noms. En fonction des effets produit par la méthode le nom diffère. La règle de base est que si la méthode comprend un suffixe tel que « -ed » ou « -ing », alors c’est un nom. Une méthode qui est un nom, renvoie une valeur. Si la méthode est un verbe à l’impératif alors elle effectue les modification directement sur l’objet (mot clé mutating
).
Voici quelques examples :
myArray.enumerate()
myArray.enumerated()
myArray.reverse()
myArray.reversed()
myArray.sort()
myArray.sorted()
GCD et Core Graphics modernisé
Grand Central Dispatch est le framework de référence pour gérer tâches asynchrone. Seulement ce framework est écrit en C et son API aussi. Afin de rendre son utilisation plus cohérente avec le langage Swift, la proposition SE-0088 redéfinit une API refondu :
// Swift 2
let queue = dispatch_queue_create("com.test.myqueue", nil)
dispatch_async(queue) {
print("Bonjour")
}
// Swift 3
let queue = DispatchQueue(label: "com.test.myqueue")
queue.async {
print("Bonjour")
}
De la même manière, Core Graphics qui est écrit en C fournit une nouvelle API pour Swift 3 (proposition SE-0044) :
// Swift 2
let ctx = UIGraphicsGetCurrentContext()
let rectangle = CGRect(x: 0, y: 0, width: 512, height: 512)
CGContextSetFillColorWithColor(ctx, UIColor.blueColor().CGColor)
CGContextSetStrokeColorWithColor(ctx, UIColor.whiteColor().CGColor)
CGContextSetLineWidth(ctx, 10)
CGContextAddRect(ctx, rectangle)
CGContextDrawPath(ctx, .FillStroke)
UIGraphicsEndImageContext()
// Swift 3
if let ctx = UIGraphicsGetCurrentContext() {
let rectangle = CGRect(x: 0, y: 0, width: 512, height: 512)
ctx.setFillColor(UIColor.blue().cgColor)
ctx.setStrokeColor(UIColor.white().cgColor)
ctx.setLineWidth(10)
ctx.addRect(rectangle)
ctx.drawPath(using: .fillStroke)
UIGraphicsEndImageContext()
}
Conclusion
L’ensemble de ces changement représente un gros travail de migration entre Swift 2.2 et Swift 3 mais à pour but de faciliter la lecture et l’apprentissage du langage. Normalement la migration entre Swift 3 et Swift 4 devra être beaucoup plus légère.