Swift – Introduction

Note – Article en cours de révision – version du 2015.09.30

Contenu

  1. Le langage de programmation Swift
  2. Le ‘playground’
  3. Concepts et syntaxe
  4. Les variables et constantes
  5. Traitements sur les chaînes de caractères
  6. Interpolation de chaînes
  7. Conversion de types
  8. Les tableaux
  9. Les dictionnaires
  10. Les boucles
  11. Les tests (if, switch)
  12. Les fonctions
  13. Les structures de données
  14. Les classes
  15. Énumérations – enum
  16. Observation de valeurs vs temps
  17. Protocoles – voir le projet Aquarium

Le langage de programmation Swift

Apple_Swift_Logo
Présenté à la conférence de la WWDC du printemps 2014,  Swift est un langage de programmation développé par la société Apple.  Il est destiné à la programmation d’applications sur les systèmes d’exploitation iOS (iPhone, iPad) et OS X (MAC).
Swift peut coexister avec l’Objective-C, langage actuel de programmation pour les systèmes d’exploitation d’Apple.  Selon la firme de Cupertino , ce nouveau langage est rapide, moderne, sécurisé et interactif.  Il contribuera probablement à atténuer la courbe d’apprentissage du développement d’application pour iOS entre autre grâce au module « playGround »
 
 


Un langage interactif – PlayGround

Mise à part la simplicité de la syntaxe du langage, une des nouveautés contribuant à l’apprentissage du langage est le module ‘PlayGround’.
PlayGround est un environnement où il est possible d’écrire des instructions Swift et d’obtenir des résultats en temps réel.
Une des façons d’obtenir ce ‘terrain de jeu’ est de créer un nouveau projet Xcode et de choisir l’option ‘Get started with a playground‘:
Action – Démarrons Xcode et sélectionnions ‘Get started with a playground’:
 
new.xcode.projet
 
Nommons  le projet:
new.playground.projet.nommer
Voici le terrain de jeux:
Intro_au_terrain_de_jeux_playground
Référence Apple


Concepts et syntaxe de Swift

Note: Ceci n’est pas un document d’introduction à la programmation.  Nous prenons pour acquis que vous maîtrisez des concepts tel que: variables, boucles, tests, fonctions, objet, méthodes, propriétés, …

Les variables

Types de base

[table]
Type, Exemple
Int – UInt – UInt32,  0 ; 1 ; 55 ; 32767 ; -2
Float – CGFloat – Double, 2.345; 3.141592 ; -105678.999
Bool, true ; false
String , ‘Paul’ ; « CSTJ.qc.ca »
ClassName, UIButton ; UIColor ; UIImage ; Personnage ; …
[/table]

Syntaxe:

var nom:Type = valeur


Exemples
:

var unEntier:Int = 99
var unReel:Float = 3.1415
var unDouble:Double = 3.1415920123456789087654321
var unBooleen:Bool = true
var uneChaine:String = "CSTJ.TIM"
var uneVue:UIView = UIView(frame : CGRectMake(0,0,50,50))

 

Déclaration inférée (le type sera déduit par Xcode)

var unEntier = 99
var unReel = 3.1415
var unDouble = 3.1415920123456789087654321
var unBooleen = true
var uneChaine = "CSTJ.TIM"
var uneVue = UIView(frame : CGRectMake(0,0,50,50))

 

Variables versus Constantes

var uneVariableMutable = 2.2    // anglais : mutable
uneVariableMutable = 1.4241
let uneVariableImmutable = 9.9  // anglais : immutable
uneVariableImmutable = 123      // erreur de compilation

Note:  Apple recommande l’utilisation de contantes à la place de variables lorsque possible.

Variables avec valeur non optionnelle

var uneChaineAvecValeurNonOptionnelle :String
println(uneChaineAvecValeurNonOptionnelle) // produira une erreur à l’exécution
uneChaineAvecValeurNonOptionnelle = nil // produira une erreur à l’exécution

 

Variables avec valeur optionnelle

var uneChaineAvecValeurOptionnelle:String?
If let uneChaineAvecValeurOptionnelleValidee = uneChaineAvecValeurOptionnelle {
println(uneChaineAvecValeurOptionnelleValidee)
} else {
println("La variable ‘uneChaineAvecValeurOptionnelle’ n’est pas initialisée.")
}

 


Traitements sur les chaines de caractères

Concaténation

let tim = "Étudiants et étudiantes de CSTJ.TIM"
let cours = "Introduction à Xcode"
var msgBienvenue = tim + ", bienvenue au cours : " + cours
msgBienvenue += "!"

Interpolation de chaines

Syntaxe:
« … \(votre code) … »
 

let anneeCours = 2014
msgBienvenue = "\(tim), bienvenue au cours : \(cours) de l'année \(anneeCours)"
let nbSemaines = 15
let heuresSemaine = 4
let msg = "À \(heuresSemaine) heures de cours par semaine pendant \(nbSemaines) semaines, le cours a une durée de \(nbSemaines * heuresSemaine) heures."

 

Comparaison de chaines

let perso1 = "Fred " + "LeToff"
let perso2 = "Fred LeToff"
if perso1 == perso2 {
  println("\(perso1) et \(perso2) sont une seule et même personne")
} else {
  println("Il n'y définitivement aucun lien de parenté entre \(perso1) et \(perso2)")
}

 

Chaines – Test insensible à la casse

let perso1 = "Fred " + "Letoff"
let perso2 = "Fred LeToff"
if perso1.lowercaseString == perso2.lowercaseString {
  println("\(perso1) et \(perso2) sont une seule et même personne")
} else {
  println("Il n'y définitivement aucun lien de parenté entre \(perso1) et \(perso2)")
}

 

Tester des chaines vides

let jeSuisUneChaineVide = ""
let moiAussi = String()
if jeSuisUneChaineVide.isEmpty && moiAussi.isEmpty {
  println("Il n'y a que du vide ici...")
}

 


Conversion de types

let prix:Float = 12.67
let quant = "2"
var total = prix * Float(quant.toInt()!)
let i = String(99)
let peutEtreunNombre = "".toInt()
if let unNombre = peutEtreunNombre {
    println("unNombre vaut \(unNombre)")
} else
{
    println("Meilleur chance la prochaine fois...")
}
// Note: pas encore de méthode String.toDouble() avec la beta3 de Xcode 6
// Conversion en utilisant un pond vers NSString
// Note pas à tester 'nil', si chaine invalide alors retourne 0.0
let UnDouble = ("1.618" as NSString).floatValue
let famille = "MAISONNEUVE.TIM"
if (famille as NSString).containsString("TIM")
{
    println("Membre de la famille...")
}
// Un autre exemple de méthodes disponibles avec la Class NSString
let motCache = "swilfkjnsljfswjftswiftswjkfswftfdf" as NSString
motCache.substringWithRange(NSMakeRange(7, 7))
println("Le mot caché est '\(motCache.substringWithRange(NSMakeRange(17, 5)))'")

 


Les tableaux

// Définition

Définition implicite

let jeSuisUnTableauDeChaine = ["Tintin", "Milou", "Tournesol"]

 

Définition explicite

let jeSuisUnTabloDeChaine:Array<String> = jeSuisUnTableauDeChaine

 

Définition explicite courte

var personnages:[String] = jeSuisUnTableauDeChaine
var tableauVideDesChaines:[String] = []

 

Tableau – Utilisation

let perso = personnages[0]
let dernierPerso = personnages[personnages.count - 1]
if !personnages.isEmpty {
println("Il y a \(personnages.count) personnage(s) dans le tableau")
}

 

Chercher la position d’un item dans un tableau

// Note: retourne nil si pas trouvé. Utiliser la syntaxe 'if let'
if let trouve = find(personnages, "Milou") {
println("Nous avons trouvé Milou à la position \(trouve) dans le tableau des personnages")
}

 

Ajouter un item dans un tableau

personnages+="Haddock"  // Ne fonctionne plus à partir de la beta 5, il faut utiliser la syntaxe de la ligne suivante
personnages.append("Haddock")

 

Retirer un item du tableau

let retrait = personnages.removeAtIndex(1)
println(retrait)

 

Vider un tableau

personnages.removeAll(keepCapacity: true)

 

Insérer un item dans un tableau

personnages.insert("Malice", atIndex: 1)
// Remplacer un (1) ou des items du tableau
// Dans l'exemple suivant: remplacer items 0 à 1 par ...
personnages[0...1] = ["Tuntun", "MunLun", "UnDun", "SunSun"] // ou 0..<2
personnages

 

Trier un tableau

personnages.sort {a, b in a < b} // voir 'closure'
personnages

 
 


Les dictionnaires

Définition: une collection de paires clé/valeur
// Syntaxe:
// … = [ clé1:valeur1, clé2:valeur2, …]

Dictionnaire – Déclaration implicite

var personnage01 = [ "Nom": "Fred", "Force": "99", "Rang":"Novice"]
// Accès simple
personnage01["Nom"]
// Accès avec test de la clé
var nom = ""
let cle = "Nom"
if let temp = personnage01[cle] {
    nom = temp
} else
{
  println("Erreur:Clé '\(cle)' invalide")
}
nom
// ********************************
var dict:[String:String]
dict = ["Nom":"Fred"]
dict["Age"] = "44"
dict

 

Dictionnaire – Déclaration explicite

let personnage02:Dictionary<String, AnyObject> = [ "Nom": "Tom", "Force": 34, "Rang":"Expert"]

 

Déclarer un Dictionnaire vide

let dictioVide = Dictionary<String, String>()

 

Utilisation d’un dictionnaire

let nomPerso1 = personnage01["Nom"]
var tabloPerso = [personnage01, personnage02]
// let forcePerso2 = tabloPerso[1]["Force"] as Int
// Note: Il est recommandé d'utiliser la syntaxe 'if set'. Un champ non défini retournera 'nil'
let force = "Force"
if let forcePerso1 = personnage01[force]?.toInt() {
println("La \(force) de Perso1 = \(forcePerso1)")
} else {
println("Erreur: Impossible d'obtenir la \(force) du personne...")
}
// Utilisation d'un dictionnaire avec des éléments de type 'AnyObject'
let personnage02:Dictionary<String, AnyObject> = [ "Nom": "Tom", "Force": 34, "Rang":"Expert"]
let force   = personnage02["Force"]     as NSNumber
let nom     = personnage02["Nom"]       as NSString
println("Mon nom est: \(nom) et j'ai une force de: \(force)")

Un tableau de dictionnaires

let personnage001/*:Dictionary<String, AnyObject>*/ = [ "Nom": "Le petit", "Force": 3, "Rang":"novice"]
let personnage002:Dictionary<String, AnyObject> = [ "Nom": "Tom", "Force": "34", "Rang":"Expert"]
var personnages02:Array<Dictionary<String, AnyObject>> = Array()
personnages02.append(personnage001)
personnages02.append(personnage002)
personnages02[0]["Rang"]
personnages02[1]["Force"]
let total = 22 + personnages02[1]["Force"]  // erreur!
// Solution
if let fp = personnages02[1]["Force"] as? Int {
    let i = fp + 22
    i
} else
{
    println("Erreur sur le type du champ 'force'")
}

Un tableau d’AnyObject

let personnage0001 = [ "Nom": "Le petit", "Force": 3,  "Rang":"novice", "Amis": ["Moi","Toi","Lui"]]
let personnage0002 = [ "Nom": "Le grand", "Force": 78, "Rang":"Expert", "Amis": ["Eux","Nous","Ils"]]
let personnage0003 = [ "Nom": "Le Boss",  "Force": 99, "Rang":"Expert", "Amis": ["Monstre rouge"]]
// AnyObject = classe de type NS
var personnages3:Array<AnyObject> = Array()
personnages3.append(personnage0001)
personnages3.append(personnage0002)
personnages3.append(personnage0003)
println(personnages3)
personnages.count
let nom3 = personnages3[1]["Nom"] as! String
let nbAmisPerso3 = (personnages3[2]["Amis"] as! NSArray).count
// Bloucler sur les éléments du tableau (voir 'for in')
// for (key,value)
for perso in personnages3 {
    let nomPerso = perso["Nom"] as! String
    println("Amis de \(nomPerso): ")
    for ami in perso["Amis"] as! NSArray {
        println("    \(ami)")
    }
    println("-------------")
}

 

Insérer une clé/valeur

Note: Ne fonctionne qu’avec <String, String>.

personnage01["Vies"] = "4"

 

Retirer une clé/valeur

Note: Ne fonctionne qu’avec <String, String>

personnage01["Rang"] = nil
personnage01.removeValueForKey("Rang")

 

NSSet – Tableau sans doublon

let personnages4 = ["Tintin", "Milou", "Tournesol", "Haddock", "Allan", "Rastapopoulos", "Dupont", "Dupond", "Muller", "Lampion", "Tapioca" ]
let unEnsemble = NSMutableSet()  // Un tableau sans doublon
var nbIterations = 0
while unEnsemble.count <= 3 {
    let unNombreAuHasard = arc4random_uniform(UInt32(count(personnages)))
    let unPersonnage = personnages[Int(unNombreAuHasard)]
    println(unPersonnage)
    unEnsemble.addObject(unPersonnage)
    nbIterations++
} // while unEnsemble.count <= 3
println("Itérations: \(nbIterations), contenu de l'ensemble: \(unEnsemble)")

 

NSCountedSet – calcule des doublons

let personnages5 = ["Tintin", "Milou", "Tournesol", "Haddock", "Allan", "Rastapopoulos", "Dupont", "Dupond", "Muller", "Lampion", "Tapioca" ]
let unEnsemble2 = NSCountedSet()  // Un tableau sans doublon
var nbIterations2 = 0
while unEnsemble2.count <= 3 {
    let unNombreAuHasard = arc4random_uniform(UInt32(count(personnages)))
    let unPersonnage = personnages[Int(unNombreAuHasard)]
    println(unPersonnage)
    unEnsemble2.addObject(unPersonnage)
    nbIterations++
}
for x in unEnsemble2 {
    println("Personnage: \(x), nb d'insertions: \(unEnsemble2.countForObject(x))")
}

 
Résultat:

Lampion
Tintin
Lampion
Dupond
Milou
Haddock
Muller
Dupond
Muller
Muller
Tournesol
Allan
Haddock
Haddock
Lampion
Dupont
Lampion
Tapioca
Personnage: Dupond, nb d'insertions: 2
Personnage: Muller, nb d'insertions: 3
Personnage: Lampion, nb d'insertions: 4
Personnage: Tintin, nb d'insertions: 1
Personnage: Allan, nb d'insertions: 1
Personnage: Milou, nb d'insertions: 1
Personnage: Tournesol, nb d'insertions: 1
Personnage: Dupont, nb d'insertions: 1
Personnage: Tapioca, nb d'insertions: 1
Personnage: Haddock, nb d'insertions: 3

 

NSIndexSet – Un ensemble d’indices

let personnages = ["Tintin", "Milou", "Tournesol", "Haddock", "Allan", "Rastapopoulos", "Dupont", "Dupond", "Muller", "Lampion", "Tapioca" ]
let indexSet = NSMutableIndexSet()
indexSet.addIndex(0)
indexSet.addIndex(2)
indexSet.addIndex(4)
(personnages as NSArray).objectsAtIndexes(indexSet) // retourne; Tintin, Tournesol et Allan

 
 
 
 


Contrôle de la séquence d’exécution

Les boucles

Syntaxe

for in range (…, ..<)

for inclusif in 0...5 {
println("La valeur de inclusif 'closed range' est \(inclusif)")
}
for exclusif in 0..<5 {
println("La valeur de exclusif 'half-open range' est \(exclusif)")
}
for car in "Bonjour le monde" {
  println(car)
}
let aventuresTintin = ["Tintin", "Milou", "Tournesol"]
for indice in 0..<aventuresTintin.count{
let msg = "Le nom du personnage \(indice + 1) est \(aventuresTintin[indice])"
}
for personnage in aventuresTintin {
 let unPersonnage = personnage
 println(unPersonnage)
}

 

for  (affectation; condition; incrémentation) {}

 

for var compteur = 0, x = 2 ; compteur < aventuresTintin.count ; compteur++ {
 x*=2
 println("Le nom du personnage \(compteur + 1) est \(aventuresTintin[compteur]) et x vaut \(x)")
}

 

while et do while

Syntaxe

var multiplesDeDeux = 2
while multiplesDeDeux < 16 {
multiplesDeDeux*=2
println(multiplesDeDeux)
}
let dernierePosition = 1
var nouvellePosition:Int
do {
nouvellePosition = Int(arc4random()) % 2 // un nombre entre 0 et 1
println(nouvellePosition)
} while nouvellePosition == dernierePosition

 


Bris de séquences (tests)

if

Syntaxe

if else (if else)

case

Syntaxe

switch valeurATester {
case valeur1: code à exécuter pour valeur1 …
case valeur2, valeur 3: code à exécuter pour valeur2 et valeur3 …
default: code si aucunes des valeurs
}

 

let unPersonnage = "Jean Valjean"
print(unPersonnage)
switch unPersonnage {
  case "Tintin", "Milou": println(" fait partie des Aventures de Tintin")
  case "Jean " + "Valjean": println(" est misérable!")
  default: println(" ne fait partie de rien...")
}
println("\n\n")
/// switch sur tous les élements d'un tableau de chaines
let expressionsHaddock = [
"Bachi-bouzouk",
"Mille millions de mille sabords",
"Bougres de faux jetons à la sauce tartare",
"Espèce de porc-épic mal embouché",
"Patagon de zoulous",
"Bougre d’extrait de cornichon",
"Simili-martien à la graisse de cabestan",
"Sombre oryctérope",
"Traîne-potence",
"Bougres d’extrait de crétins des Alpes",
]
for expression in expressionsHaddock {
  print("'\(expression)', est une expression ")
  switch count(expression) {
    case 1...15: print("facile")
    case 16..<33: print("difficile")
    default: println("impossible")
  } // switch
  println(" à retenir.")
} // for
println("\n\n")
// boucle sur les éléments contenant le mot 'Bougre'
for expression in expressionsHaddock {
  // N/A à partir de beta5: if expression.bridgeToObjectiveC().containsString("Bougre")
  if (expression as NSString).containsString("Bougre")
{
    print("'\(expression)', est une expression ")
    switch count(expression) {
      case 1...15: print("facile")
      case 16..<33: print("difficile")
      default: println("impossible")
    } // switch
    println(" à retenir.")
  } // if bougre
} // for

 
 


Les fonctions

Syntaxe
func nomDeLaFonction (nomParam1:sonType, nomParm2:sonType, …) -> typeValeurDeRetour {
instruction1
instruction…n
return expression
}

func sommeDeDeuxNombres(nb1: Double, nb2: Double ) -> Double {
  // Note: nb1 et nb2 sont des constantes. Par exemple, nb++ = erreur de compilation.
  // Il est possible de déclarer avec 'Var', Var nb1: Double.
  return nb1 + nb2
} // sommeDeDeuxNombres()
sommeDeDeuxNombres(3, 0.1415 )
sommeDeDeuxNombres(1, 2)
// Fonction sans paramètre et retour
func minimaliste() ->() {
  println("Je suis minimaliste)")
} // minimaliste()
// ou bien
func mini() {
  println("minimaliste)")
} // mini()

 

Noms externes pour les paramètres

Prenons le cas de la fonction suivante:

func déplacerPersonnage(unPerso:Personnage, vitesse:Float, x:Float, y:Float){

}

À la lecture de la ligne suivante par une tierce partie, les valeurs inscrites ne seront pas claires.

déplacerPersonnage(bob, 5, 50, 200)

Swift permet de donner des noms externes aux paramètres (un concept importé d’Ojective-C’)

func deplacerPersonnage(nomPersonnage unPerso:String, aLaVitesse vitesse:Float, vers_x x:Float, et_y y:Float) {
  let intro = "Pour votre plus grand plaisir, nous déplacons le personnage "
  println("\(intro) \(unPerso) à la position x: \(x), y: \(y) à la vitesse \(vitesse)")
}  // deplacerPersonnage()
deplacerPersonnage(nomPersonnage: "Bob", aLaVitesse: 99.9, vers_x: 50, et_y: 200)

Si nous voulons avoir comme nom externe, le nom du paramètre il suffit alors de le précéder de ‘#’
Par exemple,

func deplacerPerso(#nomPersonnage:String, #aLaVitesse:Float, #vers_x:Float, #et_y:Float) {
  let intro = "Au risque de nous répéter, nous déplacons encore une fois, le personnage "
  println("\(intro) \(nomPersonnage) à la position x: \(vers_x), y: \(et_y) à la vitesse \(aLaVitesse)")
}
deplacerPerso(nomPersonnage: "Fred", aLaVitesse: 23, vers_x: 100, et_y: 100)

 

Proposer, aux paramètres, une valeur par défaut

Note: Il faut placer les paramètres facultatifs à la fin de la déclaration. Un nom externe sera automatiquement attribué aux paramètres avec une valeur par défaut.

func deplacerSimplement(nomPersonnage:String, aLaVitesse:Float = 50, vers_x:Float = 0, et_y:Float = 0) {
  let intro = "Avec les valeurs par défaut, le personnage "
  println("\(intro) \(nomPersonnage) reviendra à la maison à la vitesse \(aLaVitesse)")
}
deplacerSimplement("Milou")
// *************
func aPlusBC(nb1:Int = 10, nb2:Int = 20, nb3:Int = 0) -> Int {
 return nb1 + nb2 + nb3
}
aPlusBC(nb2: 3)
aPlusBC(nb3:2, nb2: 3, nb1:4)

 

Fonction avec un nombre variable de paramètres (variadiques)

func unGrandMerci(#listeDesParticipants:String...){
  let debutMessage = "Nous tenons à remercier "
  let finMessage = "pour leur participation à cette démonstration."
  var lesParticipants:String = ""
  for participant:String in listeDesParticipants {
    lesParticipants += participant + ","
  } // for
  println("\(debutMessage) \(lesParticipants), \(finMessage)")
} // unGrandMerci()
unGrandMerci()
unGrandMerci(listeDesParticipants: "Tintin", "Milou", "Tounesol")

Tester la présence des paramètres variadiques

func aditionnerLesNombresEntiersSuivants(desNombres:Int...) -> Int?{
if desNombres.count == 0 {
  return nil
} // if
var total = 0
for nombre in desNombres {
  total += nombre
} // for
  return total
}
let peutEtreUnTotal = aditionnerLesNombresEntiersSuivants(23,66, 123)
if let total = peutEtreUnTotal {
  println("La somme des nombres donne \(total)")
} else {
  println("Attention, pour obtenir un total, il faut fournir des nombres...")
} // if

 

Modification de la source du paramètre

func changerNom(unNom:String) {
  unNom = "Ne fait pas cela!" // Produit une erreur car par défaut la déclaration est de type 'let'.
}  // changerNom()
func ajouterAppel(var unNom:String, appel:String) {
  unNom = appel + " " + unNom // Changera la copie du paramètre.
} // ajouterAppel()
var nomNomEst = "Jean le marin"
ajouterAppel(nomNomEst, "Monsieur")
println("Mon nom est \(nomNomEst)")
func ajouterAppel2(inout unNom:String, appel:String) {
  unNom = appel + " " + unNom // Changera la variable originale.
} // ajouterAppel2()
var nomNom = "Gille Valiquette"
ajouterAppel2(&nomNom, "Monsieur")
println("Mon nom est \(nomNom)")

 


Les ‘tuples’

let ami = ("Fred", "33", "Bon")
ami.0
let ami2 = (Nom:"Toto", Age:"99", Type:"Ancien")
ami2.Nom
//  Note, une fonction peut retourner un 'tuple'
func uneFonction() -> (String, Double){
...
  return ("PI", 3.141592)
}
let (nom,valeur) = uneFonction()

 


Les structures de données

Syntaxe

struct StructurePersonnage {
  var nom = "Non définie"
  var niveau = 0
  var force = 0.0
  var positionX = 0.0
  var positionY = 0.0
  var vies:Int = 0
} // StructurePersonnage
var jeSuisDeTypePersonnage = StructurePersonnage()
var moiAussiJeSuisDeTypePersonnage = StructurePersonnage(nom: "Bozo le clown", niveau: 3, force: 55, positionX: 0, positionY: 0, vies: 3)
jeSuisDeTypePersonnage.vies -= 1
println("jeSuisDeTypePersonnage = \(jeSuisDeTypePersonnage)")

 


Les classes (class)

Syntaxe

class ClassePersonnage {
  var nom = "Non définie"
  var niveau = 0
  var force = 0.0
  var positionX = 0.0
  var positionY = 0.0
  var vies:Int = 0
  func description() ->String {
    return "Je suis le personnage \(nom) et j'ai une force de \(force)."
  } // description()
  func deplacer(#vitesse:Int, posX:Float, posY:Float) {
    println("\(nom) se déplace vers (\(posX),\(posY)) à la vitesse \(vitesse).")
  } // deplacer()
} // ClassePersonnage
var personnage = ClassePersonnage()
personnage.nom = "La terreur des barbares"
println(personnage.description())
personnage.deplacer(vitesse: 99, posX: 100, posY: 200)

 

struct/class avec un constructeur

class ClassePersoAvecInit {
  var nom:String
  var niveau:Float
  var force:Float
  var positionX:Float
  var positionY:Float
  var vies:Int // = 0  // Va produire une erreur
  init(unNom:String){
    nom = unNom; niveau = 0; force = 0; positionX = 0; positionY = 0;
  } // init(unNom:String)
  init(unNom:String, uneForce:Float) {
    nom = unNom;
    force = uneForce
    niveau = 0; positionX = 0; positionY = 0;
  } // init(unNom:String, uneForce:Float)
  func description() ->String {
    return "Je suis le personnage \(nom) et j'ai une force de \(force)."
  } // description()
} // ClassePersoAvecInit
let perso_01 = ClassePersoAvecInit(unNom: "Tintin")
let perso_02 = ClassePersoAvecInit(unNom: "Milou", uneForce: 99)

 

Les extensions de classe

extension ClassePersoAvecInit {
  func retourAuCamp() {
    println("\(nom) revient au camp.")
  }
}
let perso_03 = ClassePersoAvecInit(unNom: "Le voyageur")
perso_03.retourAuCamp()
// ---------------------------------
// Avec une classe du langage swift:
extension String {
    func servirARien()->String{
        return "Quelle perte de temps pour '\(self)'!"
    } // servirARien()
}
let ouf = ""
ouf.servirARien()
"allo".servirARien()

 

Héritage

class PersonnageComplexe:ClassePersoAvecInit {
  func methodeQuiTue() ->String {
    return "\(nom) est prit d'une rage et anéantit tous ses adversaires... glup!"
  }
}
let mechant = PersonnageComplexe(unNom: "Boris")
println(mechant.methodeQuiTue())

 


Énumérations – enum

enum TypeDeJoueur  {
    case Novice
    case Inter
    case Expert
}
let joueur01:TypeDeJoueur
joueur01 = .Novice
if joueur01 != .Expert {
    println("Le joueur n'est pas un expert")
} // if
switch joueur01 {
case .Novice: println("Le joueur est un novice"); break
case .Inter: break
case .Expert:break
    // Note, pas besoin de clause 'default:' car tous les choix sont épuisés.
} // switch

 


Protocole – Voir le projet Aquarium

 


Observation des valeurs dans le temps

// Exemple 1: 10 nombres aléatoires entre 0..<100
for x in 0...10 {
    arc4random_uniform(100)
}
// Un peu de trigonométrie dans le temps...
for x in 0...255 {
    let t = Double(x) * sin(Double(x) * M_PI_4/4)
}
for i in 0...180
{
 let x = cos(Double(i) / M_PI_4)
}

playground-valeursVSTemps
 
Référence Apple


Document rédigé par Alain Boudreault – Juillet 2014