Cette section a été relue et corrigée, elle prend maintenant en compte les modifications apportées avec Swift 2.

La tradition veut que lorsque l’on démarre l’apprentissage d’un nouveau langage l’on commence par le fameux « Hello, World ». Avec Swift, vous pouvez vous en sortir en seulement une seule ligne :

print("Hello, world")

Si vous avez déjà écrit quelques lignes de codes en C ou en Objective-C, cette syntaxe devrait vous sembler familière. Dans Swift, cette seule ligne de code est un programme complet. Vous n’avez pas besoin d’importer une librairie additionnelle pour des fonctionnalités comme Input/Output ou la gestion des chaînes de caractères. Le code est écrit de façon globale pour tout le programme et est utilisé comme point d’entrée pour le programme, du coup vous n’avez plus besoin de la fonction main. Vous n’avez également plus besoin d’ajouter une virgule ou un point-virgule à la fin d’une déclaration.

Ce petit tour vous donne assez d’information pour démarrer l’écriture du code avec Swift en présentant les différentes façons d’accomplir une très grande variété de tâches dans vos programmes. Pas d’inquiétude si vous ne comprenez pas tout dans ce chapitre, chaque élément sera expliqué en détail dans le reste de ce tutoriel.

Pour une meilleure expérience, parcourez ce chapitre en exécutant Xcode en tâche de fond. Il vous permettra de tester les bouts de codes et d’apprécier leurs résultats immédiatement.

Valeurs simples

Utilisez let pour initier une constante et var pour déclarer une variable. La valeur d’une constante n’a pas besoin d’être connue au moment de la compilation mais vous devez lui assigner une valeur exacte au départ. Ce qui signifie que vous pouvez utiliser les constantes pour nommer une valeur et l’utiliser ensuite à de nombreux endroits.

1 var maVariable = 42
2 maVariable = 50
3 let maConstante = 42

Une constante ou une variable doivent avoir le même type que la valeur que vous lui assignez. Cependant, vous n’aurez pas toujours besoin d’indiquer le type de façon explicite. Fournir une valeur lorsque vous créez une constante ou une variable permet au compilateur de déduire son type. Dans l’exemple ci-dessus, le compileur sait que maVariable est un intégral parce-que sa valeur est un intégral (un nombre entier).

Si la valeur initiale ne présente pas suffisamment d’information (ou bien qu’il n’y a pas de valeur initiale), vous devez spécifiez le type en l’indiquant après la variable, séparé par deux points.

1 let entierImplicite = 70
2 let DoubleImplicite = 70.0
3 let DoubleExplicite: Double = 70

Exercice : Créez une constante avec le type explicite Float et la valeur 4. Quelle valeur obtenez-vous ?

Les valeurs ne sont jamais implicitement converties dans un autre type. Si vous avez besoin de convertir une valeur dans un autre type, vous devez explicitement créer une instance du type désiré.

1 let label = "La largeur est "
2 let largeur = 94
3 let largeurTotale = label + String(largeur)

Exercice : Essayer de supprimer le paramètre de conversion String de la dernière ligne. Quelle erreur obtenez-vous ?

Il y a une façon beaucoup plus simple de transformer les valeurs en chaîne de caractères : Écrire la valeur entre parenthèses et précéder ces parenthèses d’un anti-slash. Par exemple :

1 let pommes = 3
2 let oranges = 5
3 let pommesTotal = "Je possède \(pommes) pommes."
4 let fruitsTotal = "Je possède \(pommes + oranges) fruits en tout."

Exercice : Utilisez () pour inclure une virgule flottante dans un calcul avec une chaîne de caractère.

On utilise les crochets ([ ]) pour créer des tableaux et des dictionnaires, et on accède à leurs éléments en indiquant la clé ou l’index entre crochets.

 1 var shoppingList = ["poisson", "eau", "tulipes", "peinture bleue"]
 2 shoppingList[0] = "Saumon"
 3 shoppingList[1] = "bouteilles de Vittel"
 4 
 5 var metiers = [
 6     "Alexandre": "Capitaine",
 7     "Kevin": "Mécano",
 8 ]
 9 
10 metiers["Jeanne"] = "Relations publiques"

Pour créer un tableau ou un dictionnaire vide, utilisez la syntaxe d’initialisation.

1 let tableauVide = [String]()
2 let dictionnaireVide = [String:Float]()

Si le type de l’information peut être déduite par le compileur, vous pouvez initier un tableau vide avec [] et un dictionnaire vide avec [:]

1 shoppingList = []   // Je peux acheter n'importe quoi.
2 metiers = [:]

Controle des flux

La gestion des conditions s’effectue avec if et switch et les boucles avec for-in, for, while et repeat-while. Les parenthèses autour des conditions et des boucles sont optionnelles. En revanche, les accolades autour du corps de la boucle ou de la condition sont indispensables.

 1 let individuelScore = [75, 43, 103, 87, 12]
 2 var equipeScore = 0
 3 for score in individuelScore {
 4     if score > 50 {
 5         equipeScore += 3
 6     } else {
 7         equipeScore += 1
 8     }
 9 }
10 print(equipeScore)

Dans le cas d’un if, la condition doit être une expression booléenne. Ce qui veut dire qu’un code du type if score {...} est une erreur, ce n’est pas une comparaison implicite à zéro.

Vous pouvez utiliser if et let ensemble pour pallier au problème. Ces valeurs sont présentés comme optionnelles. Une valeur optionnelle contient une valeur ou contient nil pour indiquer l’absence de valeur. Pour indiquer qu’une valeur est optionnelle, on utilise le point d’interrogation.

1 var optionalString: String? = "Hello"
2 print(optionalString == nil)
3 
4 var optionalName: String? = "John Appleseed"
5 var greeting = "Hello!"
6 if let name = optionalName {
7     greeting = "Hello, \(name)"
8 }

Exercice : Changez optionalName par nil. Quelle salutation recevez-vous ? Ajoutez une clause else pour configurer une salutation différente si optionalName vaut nil.

Si la valeur optionnelle est nil, la condition est false et le code entre les accolades est ignoré. Par ailleurs, la valeur optionnelle est extraite et assignée à la constante après let, ce qui fait que la valeur devient disponible à l’intérieur du bloc de code.

Les switch supportent n’importe quel type de données et une grande variété d’opérateur de comparaison, ils ne sont pas uniquement limités aux intégrales et aux tests d’égalités.

 1 let legume = "poivre rouge"
 2 switch legume {
 3 case "celeri":
 4     let commentaireLegume = "Ajouter quelques raisins."
 5 case "concombre", "salade":
 6     let commentaireLegume = "Ça devrait faire un bon sandwich."
 7 case let x where x.hasSuffix("poivre"):
 8     let commentaireLegume = "On sent les épices \(x)?"
 9 default:
10     let commentaireLegume = "Tout a bon goût dans la soupe."
11 }

Exercice : Essayez d’enlever le case par défaut. Quelle erreur obtenez-vous ?

Après avoir exécuté le code dans le switch case qui a répondu, le programme sort de la boucle conditionnelle. L’exécution du programme ne continue pas avec le case suivant, il est donc inutile d’indiquer un break à la fin de chaque case.

Vous utiliserez for-in pour itérer (c’est a dire passer en revue) le contenu d’un dictionnaire en fournissant des noms a utiliser pour chaque paire de valeurs de clés.

 1 let nombresInterressants = [
 2     "Premier":      [2, 3, 5, 7, 11, 13],
 3     "Fibonacci":    [1, 1, 2, 3, 5, 8],
 4     "Carre":        [1, 4, 9, 16, 25],
 5 ]
 6 var lePlusGrand = 0
 7 for (type, nombres) in nombresInterressants {
 8     for nombreEnCours in nombres {
 9         if nombreEnCours > lePlusGrand {
10             lePlusGrand = nombreEnCours
11         }
12     }
13 }
14 print(lePlusGrand)

Exercice : Ajoutez une autre variable pour garder une trace du nombre qui était le plus grand, ainsi que le type du nombre que c’était.

Utilisez while pour répéter un bloc de code jusqu’a ce qu’une condition change. La condition de la boucle peut être à la fin, pour s’assurer l’exécution de la boucle au moins une fois.

 1 var n = 2
 2 while n < 100 {
 3     n = n * 2
 4 }
 5 print(n)
 6 
 7 var m = 2
 8 repeat {
 9     m = m * 2
10 } while m < 100
11 print(m)

Vous pouvez garder un index dans la boucle. Soit en utilisant .. pour faire une « zone » d’index ou en écrivant explicitement l’initialisation, la condition et incrémentation ». La boucle ci-dessous est identique à la boucle plus haut :

 1 var premiereBoucleFor = 0
 2 for i in 0..<4 {
 3     premiereBoucleFor += i
 4 }
 5 print(premiereBoucleFor)
 6 
 7 var deuxiemeBoucleFor = 0
 8 for var i = 0; i < 4; ++i {
 9     deuxiemeBoucleFor += 1
10 }
11 print(deuxiemeBoucleFor)

Utilisez ..< pour faire une zone qui ne prend pas en compte le nombre le plus grand, et utilisez ... pour une zone qui prend en compte les deux valeurs.

Fonctions et closures

On utilise le mot clef funcpour déclarer une fonction. Ensuite il suffit de lui donner un nom et des arguments entre parenthèses. On utilise ->pour séparer les noms et types des paramètres du type de ce que retourne la fonction elle-même.

1 func saluer(nom: String, jour: String) -> String {
2 	return "Bonjour \(nom), aujourd'hui nous sommes \(jour)."
3 }
4 saluer("Bob", "Mardi")

Exercice : Gardez le paramètre jour. Faites en sorte que la fonction saluer retourne l’heure du diner en fonction du jour.

On utilise un tuple pour créer une valeur composée : par exemple, pour retourner plusieurs valeurs depuis une fonction. Les élements d’un tuple peuvent être référencé par nom ou par type.

 1 func calculsStatistiques(scores: [Int]) -> (min: Int, max: Int, total: Int) {
 2 	var min = score[0]
 3 	var max = score[0]
 4 	var total = 0
 5 
 6 	for score in scores {
 7 		if score > max {
 8 			max = score
 9 		} else if score < min {
10 			min = score
11 		}
12 		total += score
13 	}
14 
15 	return (min, max, total)
16 }
17 let statistiques = calculsStatistiques ([5, 3, 100, 3, 9])
18 print(statistiques.total)
19 print(statistiques.2)

Les fonctions acceptent aussi que l’on fournisse un nombre variable d’arguments qui seront collectés via un tableau.

1 func sommeDe(nombres: Int...) -> Int {
2 	var somme = 0
3 	for nombre in nombres {
4 		somme += nombre
5 	}
6 	return somme
7 }
8 sommeDe()
9 sommeDe(42, 597, 12)

Exercice : Écrivez une fonction qui retourne la moyenne d’un nombre indéfini de valeurs.

Les fonctions peuvent être imbriquées. Les fonctions imbriquées ont accès aux variables qui ont été déclarées en dehors de la fonction. Vous pouvez utiliser les fonctions imbriquées pour organiser un code long ou complexe.

1 func retourneQuinze() -> Int {
2 	var y = 10
3 	func ajouter() {
4 		y += 5
5 	}
6 	ajouter()
7 	return y
8 }
9 retourneQuinze()

Les fonctions ont un type de première classe. Ce qui signifie qu’une fonction peut retourner une autre fonction en tant que valeur.

1 func creerIncrementeur() -> (Int -> Int) {
2 	func ajouterUn(nombre: Int) -> Int {
3 		return 1 + nombre
4 	}
5 	return ajouterUn
6 }
7 var incrementer = creerIncrementeur()
8 incrementer(7)

Une fonction peut prendre une autre fonction comme un de ses arguments.

 1 func possedeLiens(liste: [Int], condition: Int -> Bool) -> Bool {
 2 	for objet in liste {
 3 		if condition(objet) {
 4 			return true
 5 		}
 6 	}
 7 	return false
 8 }
 9 func moinsQueDix(nombre: Int) -> Bool {
10 	return nombre < 10
11 }
12 var nombres = [20, 19, 7, 12]
13 possedeLiens(nombres, condition: moinsQueDix)

Les fonctions sont en fait un cas spécial des closures: des blocs de code qui peuvent être appelés plus tard. Le code dans une closure a accès à des choses comme des variables et des fonctions qui étaient disponible entre les accolades où ils ont été créé, même si la closure est elle-même se trouve entre d’autres accolades lorsqu’elle est exécutée, nous l’avons vu avec l’exemple des fonctions imbriquées. Vous pouvez avoir une closure sans nom, simplement en entourant son code avec des parenthèses ({}). Utilisez in pour séparer les arguments et retourner son type.

1 nombres.map({
2 	(nombre: Int) -> Int in
3 	let resultat = 3 * nombre
4 	return resultat
5 })

Exercice : Réécrivez la closure pour qu’elle retourne zéro pour tous les nombres impairs.

Vous avez différentes options pour écrire une closure de façon plus concise. Lorsque le type d’une closure est déjà connu, vous n’êtes pas obligé d’indiquer son type dans les paramètres, le type retourné ou les deux. Les closures déclarées toutes seules, retournent implicitement la valeur leur propre déclaration.

1 let nombresMap = nombres.map({ nombre in 3 * nombre })
2 print(nombreMap)

Vous pouvez utiliser un nombre en paramètre plutôt qu’un nom : cette approche est spécialement utile pour les très courtes closures. Une closure passée en tant que dernier argument peut apparaître immédiatement après les parenthèses.

Lorsqu’une closure est le seul argument pour une fonction, vous pouvez ne pas mettre de parenthèses.

1 let triNombre = nombres.tri { $0 > $1 }
2 print(triNombre)

Objets et classes

Ce chapitre est en cours de traduction, merci de revenir plus tard...