Image de présentation d’un écran iOS qui affiche une présantation du langage Swift

KCorp (Exo)

Image de présentation d’un écran iOS qui affiche une présantation du langage Swift

KCorp (Exo)

Consigne

On va se retrousser les manches ! Cet exercice est un peu plus costaud, il va te permettre de pratiquer les notions qu’on a vues ensemble autour de SwiftUI, comme les property wrappers @Environment, @ObservedObject, @EnvironmentObject, et bien d’autres. L’objectif est de créer une application qui permet de manager une équipe d’esport.

Sur la vue principale, l’utilisateur pourra consulter la liste des joueurs actuellement présents dans l’équipe. Par défaut, il y en a trois. Toutes les images nécessaires sont fournies dans les assets téléchargeables. Depuis cette même vue, un bouton permet d’ajouter un nouveau joueur à l’équipe. Quand l’utilisateur appuie dessus, une modale s’ouvre avec un formulaire de création de joueur.

Dans ce formulaire, plusieurs champs sont à remplir. Le premier permet de saisir un pseudo. Ensuite, un menu déroulant propose de sélectionner le rôle du joueur, c’est-à-dire son poste (Top, Jungle, Mid, ADC ou Support pour les non initié à l’esport comme moi 😅). Un champ texte permet aussi d’indiquer le nom de l’image de profil du joueur. Ce champ est pré-rempli avec le nom « player_default », ce qui permet d’utiliser une image par défaut si l’utilisateur n’en a pas sous la main. Enfin, l’utilisateur peut sélectionner un ou plusieurs champions favoris dans une liste horizontale défilante. Lorsqu’un champion est sélectionné, son image est entourée de vert (référence-toi à la vidéo dans la partie maquette pour voir le rendu visuel).

Une fois le formulaire validé, le nouveau joueur est ajouté à l’équipe et la vue principale est automatiquement mise à jour pour refléter ce changement. Chaque joueur peut ensuite être consulté plus en détail dans une vue dédiée. Dans cette vue, on retrouve sa photo de profil, son pseudo, son rôle, ainsi que la liste de ses champions favoris. Tout en bas de l’écran, un bouton permet également de supprimer le joueur de l’application.

Tu peux télécharger les images du projet ici :  Télécharger les images

En bonus, je te fournis les données de base du projet pour que tu n’aies pas à tout remplir à la main. Je suis sympa, non ? 🫶🏼


struct Champion: Identifiable {
    let id = UUID()
    let name: String
    let imageName: String
}

let availableChampions: [Champion] = [
    Champion(name: "Ksante", imageName: "ksante"),
    Champion(name: "Jax", imageName: "jax"),
    Champion(name: "Maokai", imageName: "moakai"),
    Champion(name: "Skarner", imageName: "skarner"),
    Champion(name: "Viktor", imageName: "viktor"),
    Champion(name: "Corki", imageName: "corki"),
    Champion(name: "Kalista", imageName: "kalista"),
    Champion(name: "Draven", imageName: "draven"),
    Champion(name: "Braum", imageName: "braum"),
    Champion(name: "Fiddlesticks", imageName: "fiddlesticks"),
    Champion(name: "Jayce", imageName: "jayce")
]

class EsportTeam: ObservableObject {
    @Published var players: [Player] = [
        Player(name: "Canna", position: "Top", image: "canna", favoriteChampions: [
            Champion(name: "Jayce", imageName: "jayce"),
            Champion(name: "Jax", imageName: "jax")
        ]),
        Player(name: "Caliste", position: "ADC", image: "caliste", favoriteChampions: [
            Champion(name: "Draven", imageName: "draven"),
            Champion(name: "Kalista", imageName: "kalista"),
        ]),
        Player(name: "Targamas", position: "Support", image: "targamas", favoriteChampions: [
            Champion(name: "Braum", imageName: "braum"),
        ])
    ]
}

Pour le dernier morceau de code que je t’ai fourni ci-dessus, attention, il s’agit uniquement des données de base. Je ne t’ai pas donné le type Player, c’est à toi de le créer. Également, je t’ai volontairement mis le strict minimum ici. Il sera peut-être pertinent d’ajouter une ou plusieurs méthodes dans cette classe selon les besoins du projet.

Maquette

Capture d'écran de l'exercice, il represente une ligne avec le titre swift et sont langage, et une autre ligne avec la version de swift et sont année de sortie
Capture d'écran de l'exercice, il represente une ligne avec le titre swift et sont langage, et une autre ligne avec la version de swift et sont année de sortie
Capture d'écran de l'exercice, il represente une ligne avec le titre swift et sont langage, et une autre ligne avec la version de swift et sont année de sortie

 Tips

Cet exercice est très complet, mais largement à ta portée. Promis, aucun piège, chaque exercice que je te propose est toujours faisable avec les notions déjà à ta disposition. Comme d’habitude, je vais te donner quelques tips pour t’aider à bien démarrer ce petit projet.

Pour commencer, parlons des deux boutons de gestion de données : celui pour l’ajout et celui pour la suppression d’un joueur.

Ajouter un joueur

Tu peux t’y prendre de plusieurs façons, mais je te recommande de créer une méthode dédiée dans ton modèle. Cette méthode prendra en paramètre les mêmes propriétés que ton type Player, et à l’exécution, il te suffira d’utiliser .append() pour ajouter une nouvelle instance au tableau des joueurs.

Je te donne ici pas mal de cartes pour le mettre en place, mais le plus important, c’est que tu comprennes la mécanique. Elle reste relativement simple une fois qu’on a bien identifié les données qu’on veut manipuler.

Supprimer un joueur

Pour la suppression, ce sera encore plus direct : une simple ligne de code suffit dans ce cas, donc pas forcément besoin de méthode dédiée. Pense à utiliser les méthodes natives de Swift comme .removeAll(where:) ou remove(at:).

C’est aussi l’occasion d’introduire des notions natives comme les closures. Par exemple :


$0.id == player.id

Ici, $0 représente un élément du tableau (donc un Player dans ton cas), et .id permet de comparer son identifiant avec celui du joueur à supprimer. Cette syntaxe peut paraître un peu floue au début, c’est normal ! Mais avec un peu de pratique, tu vas vite prendre le coup. C’est beaucoup plus simple qu’il n’y paraît une fois que tu l’as utilisée quelques fois et bien analysée. N’hésite pas à consulter la correction si tu bloques trop longtemps.

Dernier tip, le Picker

Sur la vue d’ajout d’un joueur, tu remarqueras un petit menu permettant de sélectionner le rôle du joueur. Pour le mettre en place, pense au composant Picker. Il est parfaitement adapté à ce type de sélection.

Enfin, comme pour chaque projet, je te fournis la liste des SF Symbols utilisés :

Pour le plus du bouton d’ajout : plus

Pour l’icône de la poubelle du bouton de suppression : trash.fill

Pour le bouton custom re retour sur la page précédente, la flèche : chevron.left

Correction

Correction

Refactor

Note

Imagine que tu as bien avancé dans ton projet, mais tu te rends compte que le nom donné à une propriété ne te convient pas du tout finalement. Si tu devais retourner manuellement dans chaque coin du projet pour la renommer, ce serait une vraie galère… et surtout trèèèès long selon le nombre d’occurrences.

Heureusement, Xcode te facilite la vie avec l’option Refactor.

Fais simplement un clic droit sur une propriété, une fonction, une struct, etc., puis sélectionne Rename. Xcode va automatiquement te montrer tous les endroits où cet élément est utilisé.

Par exemple, si je choisis de renommer la propriété name en nameChampion, Xcode mettra à jour toutes les occurrences dans le projet d’un seul coup, sans erreur, et en une seule action.


struct Champion: Identifiable {
    let id = UUID()
    let nameChampion: String
    let imageName: String
}

let availableChampions: [Champion] = [
    Champion(nameChampion: "Ksante", imageName: "ksante"),
    Champion(nameChampion: "Jax", imageName: "jax"),
    Champion(nameChampion: "Maokai", imageName: "moakai"),
    Champion(nameChampion: "Skarner", imageName: "skarner"),
    Champion(nameChampion: "Viktor", imageName: "viktor"),
    Champion(nameChampion: "Corki", imageName: "corki"),
    Champion(nameChampion: "Kalista", imageName: "kalista"),
    Champion(nameChampion: "Draven", imageName: "draven"),
    Champion(nameChampion: "Braum", imageName: "braum"),
    Champion(nameChampion: "Fiddlesticks", imageName: "fiddlesticks"),
    Champion(nameChampion: "Jayce", imageName: "jayce")
]

Refactor

Note

Imagine que tu as bien avancé dans ton projet, mais tu te rends compte que le nom donné à une propriété ne te convient pas du tout finalement. Si tu devais retourner manuellement dans chaque coin du projet pour la renommer, ce serait une vraie galère… et surtout trèèèès long selon le nombre d’occurrences.

Heureusement, Xcode te facilite la vie avec l’option Refactor.

Fais simplement un clic droit sur une propriété, une fonction, une struct, etc., puis sélectionne Rename. Xcode va automatiquement te montrer tous les endroits où cet élément est utilisé.

Par exemple, si je choisis de renommer la propriété name en nameChampion, Xcode mettra à jour toutes les occurrences dans le projet d’un seul coup, sans erreur, et en une seule action.


struct Champion: Identifiable {
    let id = UUID()
    let nameChampion: String
    let imageName: String
}

let availableChampions: [Champion] = [
    Champion(nameChampion: "Ksante", imageName: "ksante"),
    Champion(nameChampion: "Jax", imageName: "jax"),
    Champion(nameChampion: "Maokai", imageName: "moakai"),
    Champion(nameChampion: "Skarner", imageName: "skarner"),
    Champion(nameChampion: "Viktor", imageName: "viktor"),
    Champion(nameChampion: "Corki", imageName: "corki"),
    Champion(nameChampion: "Kalista", imageName: "kalista"),
    Champion(nameChampion: "Draven", imageName: "draven"),
    Champion(nameChampion: "Braum", imageName: "braum"),
    Champion(nameChampion: "Fiddlesticks", imageName: "fiddlesticks"),
    Champion(nameChampion: "Jayce", imageName: "jayce")
]