< Previous: Concevoir la mise en page de votre interface utilisateur | Next: Devinez quel drapeau : nombres aléatoires > |
Nous allons créer un tableau de chaînes de caractères qui contiendra tous les pays qui seront utilisés pour notre jeu, et en même temps, nous allons créer une autre propriété qui conservera le score actuel du joueur - c'est un jeu, après tout !
Commençons avec les nouvelles propriétés. Tapez ces deux lignes de code directement sous les lignes @IBOutlet
que vous avez ajoutées précédemment dans ViewController.swift :
var countries = [String]()
var score = 0
Vous avez déjà rencontré la première ligne dans le projet 1 : elle crée une nouvelle propriété appelée countries
qui contient un nouveau tableau de chaînes de caractères vide. Le second crée une nouvelle propriété appelée score
qui est définie sur 0.
Ce que vous voyez ici s'appelle type inference (inférence de type). Cela signifie que Swift détermine de quel type de données est une variable ou une constante en se basant sur ce que vous y mettez. Cela signifie que a) vous devez mettre la bonne chose dans vos variables, sinon elles auront un type différent de ce que vous attendez, b) vous ne pouvez pas changer d'avis plus tard et essayer de mettre un entier dans un tableau, et c) il suffit de spécifier un type explicite si l'inférence de type de Swift est fausse.
Pour vous aider à démarrer, voici quelques exemples d'inférences de type :
var score = 0
Cela fait un Int
(entier), donc la variable contient des nombres entiers.var score = 0.0
Cela fait un Double
, qui est l’une des nombreuses façons de contenir des nombres décimaux, par ex. 3.14159.var score = "hello"
Cela crée une String
(chaîne de caractères), donc elle contient du texte.var score = ""
Même s'il n'y a pas de texte entre les guillemets, cela crée quand même une chaîne de caractères String
.var score = ["hello"]
Cela crée un [String]
avec un élément, c'est donc un tableau où chaque élément est une chaîne de caractères String
.var score = ["hello", "world"]
Cela crée un [String]
avec deux éléments, donc c'est un tableau où chaque élément est une chaîne de caractères.Il est préférable de laisser l'inférence de type de Swift faire son travail autant que possible. Cependant, vous pouvez être explicite si vous le voulez :
var score: Double = 0
Swift voit le 0 donc pense que vous voulez un Int
, mais nous le forçons explicitement à être un Double
de toute façon.var score: Float = 0.0
Swift voit le 0.0 et pense que vous voulez un Double
, mais nous le forçons explicitement à devenir un Float
. J'ai dit que Double
est l'une des nombreuses façons de conserver des nombres décimaux, et bien Float
en est une autre. En termes simples, "Double" est une forme plus précise de "Float", ce qui signifie qu’elle contient des nombres beaucoup plus grands, ou alternativement des nombres beaucoup plus précis (avec plus de chiffres après la virgule).Nous allons mettre tout cela en pratique dans les prochaines minutes. Premièrement, remplissons notre tableau de pays avec les drapeaux que nous avons, donc ajoutons ce code dans la méthode viewDidLoad()
:
countries.append("estonia")
countries.append("france")
countries.append("germany")
countries.append("ireland")
countries.append("italy")
countries.append("monaco")
countries.append("nigeria")
countries.append("poland")
countries.append("russia")
countries.append("spain")
countries.append("uk")
countries.append("us")
Ceci est identique au code que vous avez vu dans le projet 1, donc il n'y a rien à apprendre ici. Il existe un moyen plus efficace de le faire, qui consiste à tout créer sur une seule ligne. Pour ce faire, vous pouvez écrire :
countries += ["estonia", "france", "germany", "ireland", "italy", "monaco", "nigeria", "poland", "russia", "spain", "uk", "us"]
Cette ligne de code fait deux choses. Tout d'abord, elle crée un nouveau tableau contenant tous les pays. Notre tableau de pays existe déjà, et il est du type [String]
. Elle utilise ensuite quelque chose de nouveau, +=
. C'est ce qu'on appelle un opérateur, ce qui signifie qu'il fonctionne sur des variables et des constantes - il fait des choses avec elles. +
est un opérateur, comme le sont -
, *
, =
et bien d'autres encore. Ainsi, lorsque vous dites "5 + 4", vous avez une constante (5) un opérateur (+) et une autre constante (4).
Dans le cas de +=
, il combine l'opérateur +
(ajouter) et l'opérateur =
(assigner) pour faire "ajouter et assigner". Traduit, cela signifie "ajoute la chose à droite à la chose qui est à gauche" ou, dans le cas de la ligne de code de nos pays, cela signifie "ajoute le nouveau groupe de pays de droite au groupe de pays existant à gauche."
Maintenant que tous les pays sont configurés, il reste encore une ligne à mettre juste avant la fin de viewDidLoad()
:
askQuestion()
Elle appelle la méthode askQuestion()
. Cette dernière n'existe pas encore, donc Swift va se plaindre. Cependant, elle va exister dans un instant. Cette méthode askQuestion()
consistera à sélectionner des drapeaux dans le tableau, à les placer dans les boutons, puis à attendre que l'utilisateur sélectionne le bon.
Ajoutez cette nouvelle méthode sous viewDidLoad()
:
func askQuestion() {
button1.setImage(UIImage(named: countries[0]), for: .normal)
button2.setImage(UIImage(named: countries[1]), for: .normal)
button3.setImage(UIImage(named: countries[2]), for: .normal)
}
La première ligne est assez simple : nous déclarons une nouvelle méthode appelée askQuestion()
, et elle ne prend aucun paramètre. Les trois suivantes utilisent UIImage(named:)
et lisent un elément dans un tableau à partir de sa position, ce qui a déjà été utilisé dans le projet 1, donc il n'y a rien de nouveau non plus. Cependant, le reste nous montre deux nouvelles choses :
button1.setImage()
assigne une UIImage
au bouton. Le drapeau américain est déjà présent, mais cela changera lorsque askQuestion()
sera appelée.for: .normal
. La méthode setImage()
prend un second paramètre : quel état du bouton doit être changé ? Nous spécifions .normal
, ce qui signifie "l'état standard du bouton".Ce .normal
cache deux complexités de plus, que vous devez comprendre. Tout d'abord, il est utilisé comme un type de données appelé "enum", l'abréviation de enumeration. Imaginez que les boutons aient trois états : normal, en surbrillance (highlighted) et désactivé (disabled). Nous pourrions représenter ces trois états comme étant 0, 1 et 2, mais ce serait difficile à programmer - est-ce que 1 correspond à désactivé ou en surbrillance ?
Les enums résolvent ce problème en nous permettant d'utiliser des noms significatifs pour certaines choses. A la place de 0, nous pouvons écrire .normal
, et à la place de 1, nous pouvons écrire .disabled
, etc. Cela rend le code plus facile à écrire et à lire, sans aucun impact sur les performances. Parfait !
Une remarque pour ceux qui voudraient pinailler : J'ai dit que UIControlState
"est utilisé comme un type de données appelé un enum" plutôt que "est un enum", car cet exemple particulier est plutôt trouble en coulisse. En Objective-C - le langage dans lequel UIKit a été écrit - c'est une énumération, mais en Swift, il est mappé à une structure qui s'avère être utilisée comme une énumération, donc si vous voulez être techniquement correct, ce n'est pas une véritable énumération en Swift. À ce stade de votre carrière en Swift, il n’y a pas de différence, mais admettons-le : "techniquement correct" est préférable à correct.
L’autre chose que .normal
cache est ce point placé au début : pourquoi est-ce .normal
et pas simplement normal
? Eh bien, nous définissons l'image d'un UIButton
ici, donc nous devons spécifier un état du bouton pour cela. Mais .normal
peut s’appliquer à un certain nombre d’autres choses, alors comment Swift sait-il qu'il s'agit de l'état normal d'un bouton ?
Le second paramètre de setImage()
est de type UIControlState
, et Swift est intelligent : il s'attend à une valeur de type UIControlState
à l'intérieur. Ainsi, lorsque nous écrivons .normal
, il comprend que cela signifie "la valeur normal
de UIControlState
." Si vous le souhaitez, vous pouvez écrire la ligne en entier sous la forme UIControlState.normal
, mais cela ne sert à rien.
À ce stade, le jeu est prêt à fonctionner. Essayons-le.
Tout d'abord, sélectionnez le simulateur iPhone 8 en accédant au menu Product et en choisissant Destination > iPhone 8. Appuyez maintenant sur Cmd + R pour lancer le simulateur et essayer le jeu.
Vous remarquerez immédiatement deux problèmes :
Le deuxième problème devra attendre quelques minutes, mais nous pouvons résoudre le premier maintenant. L'un des nombreux avantages des vues dans iOS est qu'elles s'appuient sur ce que l'on appelle CALayer
, qui est un type de données de Core Animation, chargé de gérer l'apparence de votre vue.
Conceptuellement, CALayer
se trouve sous toutes vos UIView
s (c’est le parent de UIButton
, UITableView
, etc.), et il met à votre dispostion beaucoup d’options pour modifier l’apparence des vues, tant que cela ne vous dérange pas d'ajouter un peu de complexité. Nous allons maintenant utiliser l’une de ces options d’apparence : borderWidth
.
Le drapeau estonien a une bande blanche en bas et, comme notre contrôleur de vue a un fond blanc, toute la bande est invisible. Nous pouvons résoudre ce problème en attribuant à la couche de boutons une borderWidth
(largeur de bordure) de 1 point, ce qui tracera une ligne noire autour d’eux. Placez ces trois lignes dans viewDidLoad()
juste avant d'appeler askQuestion()
:
button1.layer.borderWidth = 1
button2.layer.borderWidth = 1
button3.layer.borderWidth = 1
Vous vous rappelez que les points et les pixels sont des choses différentes ? Dans ce cas, notre bordure sera composée d'un pixel sur les appareils non Rétina, de 2 pixels sur les appareils Rétina et de 3 pixels sur les appareils Rétina HD. Grâce à la multiplication automatique de point-à-pixel, cette bordure semblera avoir à peu près la même épaisseur sur tous les appareils.
Par défaut, la bordure de CALayer
est noire, mais vous pouvez la modifier si vous le souhaitez en utilisant le type de données UIColor
. J'ai dit que CALayer
apportait un peu plus de complexité, et c'est là que ça commence à être visible : CALayer
se situe à un niveau technique inférieur à celui de UIButton
, ce qui signifie qu'il ne comprend pas ce qu'est UIColor
. UIButton
sait ce qu'est UIColor
parce qu'ils sont tous deux au même niveau technique, mais CALayer
est inférieur à UIButton
, donc UIColor
est un mystère.
Ne désespérez pas cependant : CALayer
a sa propre méthode de définition des couleurs appelée CGColor
, qui provient du framework Core Graphics d’Apple. Comme CALayer
, il est à un niveau inférieur à celui de UIButton
, donc les deux peuvent se parler joyeusement, mais là encore tant que vous êtes satisfait avec un peu plus de complexité.
Mieux encore, UIColor
(qui se trouve au-dessus de CGColor
) est capable de convertir facilement vers et depuis CGColor
, ce qui signifie que vous n'avez pas à vous soucier de la complexité - hourra !
Donc, donc, donc : rassemblons tout cela dans du code qui change la couleur de la bordure en utilisant UIColor
et CGColor
ensemble. Placez ceci juste en-dessous des trois lignes avec borderWidth
dans viewDidLoad()
:
button1.layer.borderColor = UIColor.lightGray.cgColor
button2.layer.borderColor = UIColor.lightGray.cgColor
button3.layer.borderColor = UIColor.lightGray.cgColor
Comme vous pouvez le constater, UIColor
a une propriété appelée lightGray
qui renvoie (et bien accrochez-vous !) une instance de UIColor
qui représente une couleur gris clair. Mais nous ne pouvons pas mettre de UIColor
dans la propriété borderColor
car elle appartient à CALayer
, qui ne comprend pas ce qu'est UIColor
. Donc, nous ajoutons .cgColor
à la fin de UIColor
pour faire automatiquement la conversion en CGColor
. Parfait.
Si lightGray
ne vous intéresse pas, vous pouvez créer votre propre couleur comme ceci :
UIColor(red: 1.0, green: 0.6, blue: 0.2, alpha: 1.0).cgColor
Vous devez spécifier quatre valeurs : rouge, vert, bleu et alpha, chacune d'entre elles devant être comprise entre 0 (rien de cette couleur) et 1,0 (tout de cette couleur). Le code ci-dessus génère une couleur orangée, puis la convertit en CGColor
afin de pouvoir être affectée à la propriété borderColor
de CALayer
.
Je pense que ça suffit avec le style. Il est temps d'en faire un vrai jeu…
SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure and A/B test your entire paywall UI without any code changes or app updates.
Sponsor Hacking with Swift and reach the world's largest Swift community!
Link copied to your pasteboard.