Profitant d’un peu de calme ce WE, j’ai bossé sur ton problème, tapant un peu de code.
Première remarque : Player n’a pas besoin d’avoir un id de type UUID(). Les structures de données utilisées par SwiftUI dans l’affichage ont besoin d’un identifiant unique, mais il existe déjà : c’est le numéro de licence, normalement unique dans une structure sportive.
Pour mes tests, j’ai créé cette structure :
struct Joueur {
let nom:String
let licence:String
}
Affichage :
struct JoueurView:View {
let joueur:Joueur
var body: some View {
HStack {
Text(joueur.nom)
Spacer()
Text(joueur.licence)
}
}
}
Au début, je voulais utiliser un dictionnaire pour stocker les joueurs, mais j’y ai renoncé pour simplifier le code. On ne peut pas utiliser directement un dictionnaire dans un Foreach ou un List, ll faut passer par une petite transformation dont la syntaxe est un peu rébarbative pour un novice.
L’utilisation d’un tableau engendre une petite perte de performances, dans l’affichage des Equipes. Nous verrons plus bas pourquoi.
Plutôt que de stocker les joueurs et les équipes dans des variables @State de la vue principale, je préfère les définir dans une classe observable, regroupant toutes les données importantes de l’application. C’est plus propre.
Techniquement, une variable @Publisher d’une classe @Observable se comporte exactement comme une @State, sauf qu’elle n’a pas besoin d’être créé dans le même fichier.
class ModeleDatas : ObservableObject {
@Published var fichesJoueurs = [Joueur]()
@Published var listeEquipes = [Equipe]()
}
La fonction JoueursListeView() permet d’afficher sur l’écran une liste de joueurs stockée dans un tableau [Joueur].
struct JoueursListeView:View {
let liste:[Joueur]
var body: some View {
List(liste, id: \.licence) {
joueur in
JoueurView(joueur: joueur)
}
}
}
Le paramètre id: .licence indique à List que l’identifiant unique de chaque structure est stocké dans la propriété .licence. Cela permet d’éviter d’utiliser une structure Identifiable avec un id contenant un UUID.
List(liste, id: \.licence) {
Mine de rien, les UUID sont gourmands en mémoire, environ une centaine d’octets chacun. Ce sont de longues chaînes de caractères. Exemple d’un UUID (tiré de la doc Apple) :
E621E1F8-C36C-495A-93FC-0C247A3E6E5F
Autant éviter de les utiliser, si les données possèdent déjà une propriété unique.
J’ai codé les équipes comme ça :
struct Equipe:Identifiable {
let id = UUID()
let nom:String
let couleur:String
var score = 0
var licenceJoueurs = [String]()
}
J’ai utilisé un UUID pour identifier les équipes. En considérant que les noms sont probablement uniques, j’aurais pu les utiliser comme identifiant, mais je ne voulais pas me casser la tête à ce stade.
Les joueurs sont stockés dans un tableau contenant uniquement leurs numéros de licence.
Pour ajouter un joueur à une équipe, il suffit de faire :
equipe.licenceJoueurs.append(numeroLicence)
Et c’est tout …
C’est plus compliqué pour lire l’information, car il faut extraire les données du joueur à partir de son numéro de licence.
Voici comment j’ai fait pour afficher une équipe sur l’écran :
struct EquipeView:View {
let equipe:Equipe
@Binding var listeGlobaleJoueurs:[Joueur]
var body: some View {
VStack {
Text("Equipe : " + equipe.nom)
Text("Couleur : " + equipe.couleur)
Text("Score : " + String(equipe.score))
ForEach(equipe.licenceJoueurs, id:\.self) {
licence in
// Recherche Joueur avec cette licence
if let joueur = listeGlobaleJoueurs.first(where: { $0.licence == licence}) {
JoueurView(joueur: joueur)
}
}
}
}
}
EquipeView a besoin de deux paramètres : l’équipe et le tableau contenant les joueurs.
Si j’avais utilisé un dictionnaire, ce serait très simple de récupérer un joueur à partir de son numéro de licence.
joueur = dico[numeroLicence]
Mais ce n’est pas possible, puisque c’est un tableau. On peut faire la même chose en demandant à l’application de fouiller le tableau, à la recherche d’un joueur ayant le bon numéro de licence.
if let joueur = listeGlobaleJoueurs.first(where: { $0.licence == licence}) {
JoueurView(joueur: joueur)
}
Les tableaux de Swift ont une fonction first() permettant de rechercher la première occurence d’un objet, correspondant à un critère de recherche.
La recherche d’un objet dans un dictionnaire est trés rapide, parce que les clés sont triés et classés dans un arbre binaire.
C’est plus lent avec une fonction de recherche dans un tableau, l’application devant lire chaque case, jusqu’à obtenir le bon résultat. Ce n’est pas significatif avec un petit nombre d’éléments. Si par contre, le tableau contient des milliers d’objets, il est impératif d’utiliser un dictionnaire pour accélérer la recherche, sous peine de ralentissement de l’application.
Des questions ? Il y a encore d’autres choses à dire, mais pour aller plus loin, je dois m’assurer que tu comprennes bien ces bases.