FIREBASE CRUD récupérer un objet

Etape 10

Un objet (un film) a été créé, et enregistré sur la base de donnée Firebase.

Pour le récupérer et l'afficher dans notre application :

MODELE de l'OBJET

Créer le modèle de la fiche d'un film, dans un nouveau fichier "Movie.swift".

Attention de bien faire correspondre le nom des propriétés avec celui de l'objet créé dans le tableau "var data : [String: Any]" de la méthode "sendMovie()". C'est le nom donné aux champs de base de données Firebase.

import Firebase
class Movie {

    var ref: DocumentReference
    var uid: String
    var titre: String
    var part: String
    var year: String
    var director: String
    var pitch: String
    var movieImageUrl: String?

    init(_ document: DocumentSnapshot) {
        ref = document.reference
        uid = document.documentID
        let data = document.data() ?? [:]
        titre = data["titre"] as? String ?? ""
        part = data["part"] as? String ?? ""
        year = data["year"] as? String ?? ""
        director = data["director"] as? String ?? ""
        pitch = data["pitch"] as? String ?? ""
        movieImageUrl = data["movieImageUrl"] as? String
    }
}

Dans "FireDatabase", une méthode ("getMe()") a été créé pour récupérer les données du profil.

De la même manière, une méthode "getMovies()" est créée avec une complétion qui va récupérée un tableau de Movie :

func getMovies(completion: (([Movie]?, Error?) -> Void)?) {  
    }

Cette complétion sera utilisée dans une autre fonction, pour la rendre accessible, créer une propriété, en copiant/collant la complétion :

var movieCompletion: (([Movie]?, Error?) -> Void)?

QUERY

Des chemins de collections ont été définis pour chaque database. Une demande (query) est définie, ici avec un tri :

func movieBaseQuery() -> Query {
        return moviesCollection.order(by: "part", descending: false)
        //retourne une collection triée par épisodes croissants
    }

Implémenter la méthode "getMovies()" :

func getMovies(completion: (([Movie]?, Error?) -> Void)?) {
        self.movieCompletion = completion
        movieBaseQuery().addSnapshotListener(listener: FIRQuerySnapshotBlock)
    }

Ce listener est une closure.

movieBaseQuery().addSnapshotListener { (QuerySnapshot?, Error?) in
            code
        }

Les réponses et erreurs sont traitées dans une autre méthode "handleListener()", qui aura en paramètres un snapshot de type QuerySnapshot, et une erreur.

func handleListener(_ snapshot: QuerySnapshot?, _ error: Error?) {
        if error != nil {
            movieCompletion?(nil, error)
        }
        if snapshot != nil {
            //il y a une réponse, on transforme les snaps en Movie
            let documents = snapshot!.documents //on met les snaps dans un tableau de documents
            for document in documents {
                print(document.data()) //pour vérifier la réception
            }
        }
    }

La méthode "getMovies() devient :

func getMovies(completion: (([Movie]?, Error?) -> Void)?) {
        self.movieCompletion = completion
        movieBaseQuery().addSnapshotListener(handleListener(_:_:))
    }

Pour tester la réception des snaps, dans le controller qui doit afficher la liste de film, ajouter dans le "viewDidLoad()"

var movies: [Movie] = []
override func viewDidLoad() {
        super.viewDidLoad()
        FireDatabase().getMovies { (movies, error) in
            //
        }
    }

Dans la console, s'affiche un tableau avec les données des films récupérés

L'AFFICHAGE

Les données des films stockés sur la database Firebase sont bien récupérées. La méthode "handleListener()" est modifiée pour les préparer dans un tableau "movies" :

...
if snapshot != nil {
            //il y a une réponse, on transforme les snaps en Movie
            var movies: [Movie] = []        //création d'un tableau de movie vide
            let documents = snapshot!.documents //on met les snaps dans un tableau de documents
            for document in documents {
                movies.append(Movie(document))      //chaque document est mis au format Movie et ajouter au tableau Movies
            }
            movieCompletion?(movies, nil)
        }

Dans le controller qui affiche la liste des films, implémenter une nouvelle méthode "retrieveMovies()" pour appeler la méthode "getMovies()", et ajouter les films récupérés dans le tableau de movies :

func retrieveMovies() {
        FireDatabase().getMovies { (movies, error) in
            if let newMovies = movies {
                self.movies = newMovies
                self.tableView.reloadData()
            }
        }
    }

Cette méthode est appelée dans le "viewWillAppear()"

Capture d’écran 2021-03-01 à 10.03.24.png

Ici une simple liste avec deux données. La sélection d'une cellule peut ouvrir une vue détaillée pour afficher la fiche détaillée du film.

EP1.jpg