Dans la vue :
@State private var display = "0"
@State private var previousValue: Double? = nil
@State private var currentOperator: Operateur? = nil
@State private var isEnteringNewNumber = truedisplay
- C’est le texte affiché à l’écran (par exemple
"0","123","3.14"). - Toute la saisie utilisateur (chiffres, point) modifie ``display`.
- C’est aussi à partir de display qu’on calcule la valeur numérique courante.
previousValue
- C’est la mémoire de la calculatrice.
- Elle stocke le premier opérande quand tu tapes quelque chose comme :
12 + 5 =previousValuesera12,displaycontiendra 5 juste avant de faire le calcul. Quand on enchaîne des opérations (2 + 3 + 4 =), previousValue est mise à jour à chaque étape.
currentOperator
- C’est l’opérateur actuellement choisi :
.addition,.soustraction,.multiplication,.division. - Il est mis à jour quand tu appuies sur
+,-,×,÷. - Il est utilisé au moment de
tapOperator(chaînage) ettapEquals.
isEnteringNewNumber
- Booléen qui dit si on est en train :
- de commencer un nouveau nombre (
true), - ou de continuer à taper le nombre courant (
false).
- de commencer un nouveau nombre (
- Exemple :
- Au début :
display = "0",isEnteringNewNumber = true. - Tu tapes
7→ on remplace"0"par"7", puisisEnteringNewNumber = false. - Tu appuies sur
+→ la prochaine fois que tu tapes une touche chiffre, on doit repartir à zéro pour le nouvel opérande →isEnteringNewNumber = true.
- Au début :
currentValue
private var currentValue: Double {
Double(display) ?? 0
}- Convertit le texte affiché (
display) enDouble. - Si la conversion échoue (théoriquement ça ne devrait pas arriver), ça retourne
0. - C’est la valeur numérique utilisée dans tous les calculs.
format(_ value: Double)
private func format(_ value: Double) -> String {
if value.rounded() == value {
return String(Int(value))
} else {
return String(value)
}
}- Sert à rendre le résultat plus joli :
- Si la valeur est un entier (
5.0) → on affiche"5". - Sinon on garde le nombre avec décimales (
3.14).
- Si la valeur est un entier (
- Ça évite les affichages du genre
2.0pour2.
private func tapDigit(_ digit: String) {
if isEnteringNewNumber || display == "0" {
display = digit
} else {
display.append(digit)
}
isEnteringNewNumber = false
}Rôle :
- Gérer la saisie d’un chiffre (
"0"à"9"). Logique : - Si on commence un nouveau nombre (
isEnteringNewNumber == true) **ou** que l’écran montre"0"` :- On remplace le contenu par le nouveau chiffre (
display = digit). - Exemple : départ
"0", tu tapes"7"→ écran"7".
- On remplace le contenu par le nouveau chiffre (
- Sinon :
- On concatène le chiffre à la fin (
display.append(digit)). - Exemple : écran
"12", tu tapes"3"→"123".
- On concatène le chiffre à la fin (
Puis :
isEnteringNewNumber = false- On indique qu’on est maintenant en train de continuer la saisie de ce nombre (et non d’en commencer un nouveau).
private func tapDecimal() {
if isEnteringNewNumber {
display = "0."
isEnteringNewNumber = false
} else if !display.contains(".") {
display.append(".")
}
}Cas 1 : on commence un nouveau nombre
- Si
isEnteringNewNumberesttrue:- On affiche
"0."(comme sur une vraie calculatrice si tu appuies d’abord sur.). - Puis
isEnteringNewNumber = false.
- On affiche
Cas 2 : on est en train de taper un nombre
- Si on n’est pas en début de nombre :
- On vérifie que
displayne contient pas déjà un point (.). - S’il n’y en a pas, on l’ajoute à la fin (
display.append(".")).
- On vérifie que
🎯 Objectif : empêcher deux points décimaux dans le même nombre.
private func tapOperator(_ op: Operateur) {
let current = currentValue
if let prev = previousValue, let currentOp = currentOperator, !isEnteringNewNumber {
let result = currentOp.appliquer(prev, current)
previousValue = result
display = format(result)
} else {
previousValue = current
}
currentOperator = op
isEnteringNewNumber = true
}C’est là que ça devient intéressant 😄
let current = currentValue- On convertit ce qui est affiché en nombre (
Double).
Cas A : il y a déjà un calcul en cours
if let prev = previousValue, let currentOp = currentOperator, !isEnteringNewNumber {
let result = currentOp.appliquer(prev, current)
previousValue = result
display = format(result)
}Ce if vérifie trois choses :
-
previousValueexiste déjà.
→ on a déjà un premier nombre mémorisé, -
currentOperatorexiste.
→ on a déjà un opérateur en attente, -
!isEnteringNewNumber.
→ on vient réellement de taper un nouveau nombre, on ne fait pas juste changer d’opérateur.
Dans ce cas :
-
On effectue :
result = currentOp.appliquer(prev, current).- Par exemple : tu as tapé
2 + 3, puis tu appuies sur + encore → on calcule2 + 3.
- Par exemple : tu as tapé
-
On met à jour :
-
previousValue = result(pour pouvoir enchaîner avec le suivant), -
display = format(result)pour afficher le résultat intermédiaire.
➡️ C’est ce qui permet de faire :
2 + 3 + 4 + 5 =
et d’obtenir la somme en enchaînant les opérations.
Cas B : c’est le premier opérateur
else {
previousValue = current
}- Si on n’a pas encore de
previousValueou d’opérateur, - Alors on se contente de mémoriser la valeur courante comme premier opérande.
currentOperator = op
isEnteringNewNumber = truecurrentOperator = op:- On mémorise l’opérateur choisi maintenant (
+,-,×,÷).
- On mémorise l’opérateur choisi maintenant (
isEnteringNewNumber = true:- Le prochain chiffre tapé correspondra à un nouveau nombre (le second opérande).
private func tapEquals() {
let current = currentValue
if let prev = previousValue, let op = currentOperator {
let result = op.appliquer(prev, current)
display = format(result)
previousValue = nil
currentOperator = nil
isEnteringNewNumber = true
}
}Étapes :
- On lit la valeur courante (
current). - On vérifie qu’on a :
- un
previousValue(premier opérande), - un
currentOperator(opération en attente).
Si c’est le cas :
- On calcule :
result = op.appliquer(prev, current)(par exemple :12 + 5,3 × 4, etc.) - On affiche le résultat :
display = format(result).
Puis on reset l’état :
previousValue = nilcurrentOperator = nilisEnteringNewNumber = true(pour que la prochaine saisie remplace le résultat).
🎯 Conclusion :
tapEquals termine l’opération en cours et remet la calculatrice dans un état “prête pour un nouveau calcul”.
private func tapClear() {
display = "0"
previousValue = nil
currentOperator = nil
isEnteringNewNumber = true
}Cette fonction remet toute la calculatrice à zéro :
- écran :
"0", - aucune valeur mémorisée,
- aucun opérateur en attente,
- prochaine saisie = nouveau nombre.
private func toggleSign() {
let value = currentValue
let newValue = -value
display = format(newValue)
isEnteringNewNumber = true
}- On lit la valeur actuelle.
- On calcule son opposé (
-value). - On l’affiche.
- On se met en mode “nouveau nombre” pour que la prochaine saisie remplace ce résultat.
private func applyPercent() {
let value = currentValue
let newValue = value / 100.0
display = format(newValue)
isEnteringNewNumber = true
}- Transforme la valeur actuelle en pourcentage (ex.
50→0.5). - Met à jour l’affichage.
- Prépare la calculatrice à recevoir un nouveau nombre.
let result = op.appliquer(prev, current)C’est l’énumération Operateur qui fait le vrai travail mathématique :
.addition→a + b.soustraction→a - b.multiplication→a * b.division→ gestion deb == 0 + a / bLa vue, elle, ne fait que :
- lire les nombres (
currentValue,previousValue), - appeler
appliquer, - afficher le résultat avec
format.