FIREBASE CRUD ajouter une photo de profil

FIREBASE CRUD ajouter une photo de profil

Etape 5

La photo de profil peut être, par exemple, dans une cellule de collection, ou associée à un bouton, ou encore une simple image. L'action qui va déclencher l'ajout de la photo est la sélection de la cellule, ou l'appui sur le bouton, ou le touché de la vue. Dans notre exemple, c'est le touché de la vue.

Deux possibilités, soit ajouter une méthode existante, en override "touchesBegan", soit ajouter un TapGestureRecognizer sur l'image, le relier au controller en "@IBAction" (dans le story, icône dans la barre du haut du view controller) et implémenter l'action.

Ici, "touchesBegan" est utilisée,

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 
// on vérifie s'il y a un touché = le tableau de touché "Set<UITouch>" n'est pas vide = au moins 1 touché
        guard let touch = touches.first else { return }
//on vérifie qu'il y a un user et que c'est bien moi pour changer le profil !!!
        guard let myUser = user else { return }
        guard let myId = FireAuth().myId() else { return }
        guard myId == myUser.uid else { return }
//on définit la zône où le touché est actif
        if touch.view == profilImage {
            //action
        } else {
            return
        }
    }

Pour que le geste soit reconnu par la vue, dans le storyboard, sélectionner la vue, et dans inspecteur d'attributs, cocher la case "User Interaction Enabled". Ou ajouter la propriété à la vue :

//Autorise les interactions avec l'utilisateur
        imageView.isUserInteractionEnabled = true

En appuyant sur la vue, une action est déclenchée. Cette action fait apparaître une alerte donnant le choix de prendre une photo avec l'appareil, ou en sélectionner une dans l'album.

Il est possible d'accéder directement à l'album, (voir annexe à la fin).

Pour cela un "ImagePickerController" est nécessaire, ainsi qu'un "UINavigationControllerDelegate". Ajouter en extension :

extension ProfilController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        dismiss(animated: true, completion: nil)
    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {

  //imagePicker a un tableau d'image = info
  //l'image est soit éditée(une partie avec le zoom), ou originale

        if let editedImage = info[.editedImage] as? UIImage {
            profilImage.image = editedImage.withRenderingMode(.alwaysOriginal)

        } else if let originalImage = info[.originalImage] as? UIImage {
            profilImage.image = originalImage.withRenderingMode(.alwaysOriginal)
        }
        dismiss(animated: true, completion: nil)
    }
}

Définition de l'alerte :

func profilImageAlert() {
        let photoSourceController = UIAlertController(title: "", message: "Choississez votre image", preferredStyle: .actionSheet)

        let cameraAction = UIAlertAction(title: "Appareil photo", style: .default) { (action) in
            if UIImagePickerController.isSourceTypeAvailable(.camera) {
                let imagePicker = UIImagePickerController()
                imagePicker.delegate = self
                imagePicker.allowsEditing = true     //permet de zoomer l'image
                imagePicker.sourceType = .camera

                self.present(imagePicker, animated: true, completion: nil)
            }
        }
        let albumPhotoAction = UIAlertAction(title: "Album photo", style: .default) { (action) in
            if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
                let imagePicker = UIImagePickerController()
                imagePicker.delegate = self
                imagePicker.allowsEditing = true     //permet de zoomer l'image
                imagePicker.sourceType = .photoLibrary

                self.present(imagePicker, animated: true, completion: nil)
            }
        }

        photoSourceController.addAction(cameraAction)
        photoSourceController.addAction(albumPhotoAction)

        present(photoSourceController, animated: true, completion: nil)
    }

Pour finir appeler cette méthode dans "touchesBegan" au niveau de l'action.

if touch.view == profilImage {
            //action
            profilImageAlert()

Il reste à compléter le fichier "Info.plist", en ajoutant deux autorisations "key/Value" pour l'accès à l'album photo et à l'appareil photo

Capture d’écran 2021-03-09 à 15.37.44.png

ANNEXE

Accéder directement à l'album photo, sans popup préalable.

L'extension ProfilController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {} reste inchangée.

A la place de la méthode "profilImageAlert()", implémenter une nouvelle méthode, ou implémenter l'IBAction du tapgestureRecognizer

func profilImage() {

    let imagePickerController = UIImagePickerController()
    imagePickerController.sourceType = .photoLibrary
    imagePickerController.delegate = self
    present(imagePickerController, animated: true, completion: nil)

Ajouter une image dans le simulateur

Quand l'application est lancée dans le simulateur, pour ajouter une image stockée sur le mac, il suffit de faire glisser cette image sur le simulateur, à l'emplacement prévue de l'image. Cette image est ajoutée à l'album. En revenant sur l'application dans le simulateur, l'image peut être sélectionnée.


Quand on utilise des images (profile, publications, etc...) stockées sur une base de données, il peut être intéressant de les garder en cache dans l'appareil, pour éviter de les télécharger à chaque fois (temps d'attente, et coûts).

On peut utiliser la librairie "SDWebImage" de CocoaPods. (voir story suivante : "FIREBASE CRUD image en cache")