TableView Sections avec des dates?

Manipuler des Dates seules ne sert pas a grand chose. C’est pourquoi j’ai créé une classe Evenement encapsulant une date et une chaîne décrivant ce qui doit être fait à cette occasion.

class Evenement {
    var date = Date()
    var description = "Un événement quelconque »
}

Pour faire des tests en condition réel, j’ai développé un générateur aléatoire d’événements.

// Quelques événements possibles
let evenementActions = ["Manger des pommes",
                            "Sortir le chien",
                            "Acheter un billet de train",
                            "Enregistrer les Feux de l'Amour",
                            "Repeindre la cuisine",
                            "Faire les courses",
                            "Aller chez le Coiffeur",
                            "Se brosser les dents",
                            "Aller voir le dentiste",
                            "Acheter les cadeaux de Noël »
    ]

    func creerDescriptionAleatoire() -> String {
            let nombreActions = UInt32(evenementActions.count)
            let numAction = Int(arc4random_uniform(nombreActions))
            return evenementActions[numAction]
    }

func creerDateAleatoire() -> Date {
    var date = Date()
    let nbJours:UInt32 = 60*60*24*5
    let delaiAleatoire = TimeInterval(arc4random_uniform(nbJours))
    date.addTimeInterval(delaiAleatoire)
    return date
}

// Création Evenement Aléatoire
func creerEvenementAleatoire() -> Evenement {
    let evenement = Evenement()
    evenement.date = creerDateAleatoire()
    evenement.description = creerDescriptionAleatoire()
    return evenement
}

La fonction créerEvenementAleatoire peut être insérée dans une boucle pour fabriquer un tableau (une liste) d’événements.

    func creerListeEvenements(taille:Int) -> [Evenement] {
        var liste = [Evenement]()
        for _ in 1...taille {
            liste.append(creerEvenementAleatoire())
        }
        return liste
    }

Pour tester j’ai ajouté un fonction d’affichage. Et roulez jeunesse …

func afficherListeEvenement(liste:[Evenement]) {
    for ev in liste {
        print (ev.date, " : ", ev.description)
    }
}

Mise en application :

    // Création d'une liste de 10 événements aléatoires
    let listeEvenementsAleatoires = creerListeEvenements(taille: 10)
    //
    // Affichage
    print ()
    print ("---")
    print ("Liste événements aléatoires")
    afficherListeEvenement(liste: listeEvenementsAleatoires)

Affichage :


Liste événements aléatoires
2018-02-11 13:06:42 +0000 : Faire les courses
2018-02-14 05:37:33 +0000 : Acheter un billet de train
2018-02-14 01:54:48 +0000 : Acheter les cadeaux de Noël
2018-02-13 17:42:12 +0000 : Enregistrer les Feux de l’Amour
2018-02-13 17:23:06 +0000 : Se brosser les dents
2018-02-13 18:20:37 +0000 : Repeindre la cuisine
2018-02-13 00:46:58 +0000 : Acheter les cadeaux de Noël
2018-02-11 01:28:09 +0000 : Aller chez le Coiffeur
2018-02-13 13:46:36 +0000 : Aller voir le dentiste
2018-02-11 14:55:57 +0000 : Sortir le chien

Certains événements se répètent. C’est normal le générateur de descriptions n’ayant pas beaucoup de phrases à sa disposition.


Etape suivante : comment trier les objets Evenement en basant sur leurs Dates ?

// Tri des objets Evenements en fonction des Dates
let triage = listeEvenementsAleatoires.sorted { $0.date<$1.date }

La closure de la méthode .sorted permet de définir une condition de triage basée sur n’importe quelle propriété des objets contenus dans le tableau.

Exemple :

    // Tri des objets Evenements en fonction des Dates
    let triage = listeEvenementsAleatoires.sorted { $0.date<$1.date }
    
    print ()
    print ("---")
    print ("Liste événements triés")
    afficherListeEvenement(liste: triage)

Affichage :


Liste événements triés
2018-02-11 01:28:09 +0000 : Aller chez le Coiffeur
2018-02-11 13:06:42 +0000 : Faire les courses
2018-02-11 14:55:57 +0000 : Sortir le chien
2018-02-13 00:46:58 +0000 : Acheter les cadeaux de Noël
2018-02-13 13:46:36 +0000 : Aller voir le dentiste
2018-02-13 17:23:06 +0000 : Se brosser les dents
2018-02-13 17:42:12 +0000 : Enregistrer les Feux de l’Amour
2018-02-13 18:20:37 +0000 : Repeindre la cuisine
2018-02-14 01:54:48 +0000 : Acheter les cadeaux de Noël
2018-02-14 05:37:33 +0000 : Acheter un billet de train


Pour résoudre ton problème d’affichage dans une TableView j’ai codé une autre méthode analysant une table d’événements pour retourner un tableau contenant une liste de tableaux.

typealias ListeDeJours = [[Evenement]]

func decoupageEnListeDeTableaux(liste:[Evenement]) -> ListeDeJours {
        let calendrier = Calendar.current
        var listeDesTableaux = ListeDeJours()
        var tableauTampon = [Evenement]()
        
        // Traitement du premier élément du tableau
        var jourCourant = liste[0].date
        
        for evenement in liste {
            // L'événement se produit-il à la même date que le jourCourant ?
            // Si non => Création d'un nouveau tableau
            if !calendrier.isDate(evenement.date,
                                 equalTo: jourCourant,
                                 toGranularity: .day) {
                // Actualisation du jour courant
                jourCourant = evenement.date
                // On archive le tableau courant dans la liste des tableaux
                listeDesTableaux.append(tableauTampon)
                // Création nouveau tableau
                tableauTampon = [Evenement]()
            }
            
            // On ajoute l'événement dans le tableau courant
            tableauTampon.append(evenement)
        }
        
        // On archive le dernier tableau dans la liste des Tableaux
        listeDesTableaux.append(tableauTampon)
        
        return listeDesTableaux
    }

Utilisation :

// Création d'une liste de 10 événements aléatoires
let listeEvenementsAleatoires = creerListeEvenements(taille: 10)
// Tri des Evenements en fonction des Dates
let triage = listeEvenementsAleatoires.sorted { $0.date<$1.date }
// Découpage des événements en fonction des jours
let listeDeTableaux = decoupageEnListeDeTableaux(liste: triage)

C’est pratique parce que la liste de tableaux contient toutes les informations nécessaires à l’affichage dans la tableView.

Le nombre de section c’est la taille de la liste de tableaux

let nbSections = listeDeTableaux.count

Pour connaître tous les événements se produisant à une date donnée, il suffit de parcourir le tableau correspondant.

Pour vérifier si cela fonctionne, j’ai écris une petite méthode affichant le contenu de la liste de tableaux.

func affichageListeDeTableaux(liste:ListeDeJours) {
    let nombreJours = liste.count
    print ()
    print ("----------------------")
    print ("Il y a ", nombreJours, " jours dans le tableau")
    
    for tableau in liste {
        // Lecture date du premier élément du tableau
        let date = tableau[0].date
        
        // Formatage Date au format français
        let france = DateFormatter()
        // Je force l'affichage de la Date en français
        // (par défaut le format dépend de la langue courante du device)
        france.locale = Locale(identifier: "FR-fr")
        france.dateStyle = .long
        france.timeStyle = .none
        let dateFrance = france.string(from: date)
        
        print ("---")
        print (dateFrance)
        // Lecture des évenements d'un sous-tableau
        for evenement in tableau {
            let description = evenement.description
            print (" ", description)
        }
    }
}

Affichage :

----------------------
Il y a  3  jours dans le tableau
---
11 février 2018
  Aller chez le Coiffeur
  Faire les courses
  Sortir le chien
---
13 février 2018
  Acheter les cadeaux de Noël
  Aller voir le dentiste
  Se brosser les dents
  Enregistrer les Feux de l'Amour
  Repeindre la cuisine
---
14 février 2018
  Acheter les cadeaux de Noël
  Acheter un billet de train

Tu peux t’inspirer de l’exemple pour peupler ta TableView. Il suffit juste d’associer chaque élément de la liste de tableau avec une cellule de la TableView.


J’ai commenté le code. Si tu ne comprend pas quelque chose, n’hésite pas à demander. Le concept d’un tableau contenant d’autres tableaux est peut-être un peu déroutant pour un novice.

J’ai utilisé des fonctions du calendrier (objet Calendar) pour savoir si une date appartient au même jour qu’une autre. C’est très pratique. Même chose pour afficher les dates au format habituel français (14 février 2018 au lieu de 14-02-2018).

EDIT : J’ai édité plusieurs fois le texte, pour des problèmes de mise en page.

1 « J'aime »

Waouw, un grand merci pour cette réponse hyper complète! :smiley:
Je teste ça dès que je sais et je te tiens au courant :slight_smile:

A ton service. Cela m’a permis d’approfondir deux ou trois trucs que je n’avais pas encore abordé.