Laboratoire de programmation Firebase iOS Swift

1. Vue d'ensemble

2efe6805ef369641.png

Bienvenue dans l'atelier de programmation Friendly Chat. Dans cet atelier de programmation, vous apprendrez à utiliser la plate-forme Firebase pour créer des applications iOS. Vous implémenterez un client de chat et surveillerez ses performances à l'aide de Firebase.

Ce que vous apprendrez

  • Autoriser les utilisateurs à se connecter.
  • Synchronisez les données à l'aide de la base de données Firebase Realtime.
  • Stockez les fichiers binaires dans Firebase Storage.

Ce dont vous aurez besoin

  • Xcode
  • Cosses de cacao
  • Un appareil de test avec iOS 8.0+ ou un simulateur

Comment allez-vous utiliser ce tutoriel ?

Lisez-le uniquement Lisez-le et complétez les exercices

Comment évalueriez-vous votre expérience dans la création d’applications iOS ?

Novice Intermédiaire Compétent

2. Obtenez l'exemple de code

Clonez le référentiel GitHub à partir de la ligne de commande.

$ git clone https://github.com/firebase/codelab-friendlychat-ios

3. Créez l'application de démarrage

2f4c98d858c453fe.png

Pour créer l'application de démarrage :

  1. Dans une fenêtre de terminal, accédez au android_studio_folder.png Répertoire ios-starter/swift-starter à partir de votre exemple de téléchargement de code
  2. Exécutez pod install --repo-update
  3. Ouvrez le fichier FriendlyChatSwift.xcworkspace pour ouvrir le projet dans Xcode.
  4. Clique le 98205811bbed9d74.png Bouton Exécuter .

Vous devriez voir l’écran d’accueil de Friendly Chat apparaître après quelques secondes. L'interface utilisateur devrait apparaître. Cependant, à ce stade, vous ne pouvez pas vous connecter, envoyer ou recevoir des messages. L'application s'abandonnera avec une exception jusqu'à ce que vous ayez terminé l'étape suivante.

4. Créer un projet de console Firebase

Créer un projet

Dans la console Firebase , sélectionnez Ajouter un projet .

Appelez le projet FriendlyChat , puis cliquez sur Create Project .

Capture d'écran du 06/11/2015 14:13:39.png

Connectez votre application iOS

  1. Depuis l'écran Présentation du projet de votre nouveau projet, cliquez sur Ajouter Firebase à votre application iOS .
  2. Saisissez l'ID du bundle, sous la forme " com.google.firebase.codelab.FriendlyChatSwift ".
  3. Entrez l'identifiant de l'App Store comme " 123456 ".
  4. Cliquez sur Enregistrer l'application .

Ajoutez le fichier GoogleService-Info.plist à votre application

Sur le deuxième écran, cliquez sur Télécharger GoogleService-Info.plist pour télécharger un fichier de configuration contenant toutes les métadonnées Firebase nécessaires pour votre application. Copiez ce fichier dans votre application et ajoutez-le à la cible FriendlyChatSwift .

Vous pouvez maintenant cliquer sur le « x » dans le coin supérieur droit de la fenêtre contextuelle pour la fermer – en sautant les étapes 3 et 4 – car vous effectuerez ces étapes ici.

19d59efb213ddbdc.png

Importer le module Firebase

Commencez par vous assurer que le module Firebase est importé.

AppDelegate.swift , FCViewController.swift

import Firebase

Configurer Firebase dans AppDelegate

Utilisez la méthode « configure » ​​dans FirebaseApp dans la fonction application:didFinishLaunchingWithOptions pour configurer les services Firebase sous-jacents à partir de votre fichier .plist.

AppDelegate.swift

  func application(_ application: UIApplication, didFinishLaunchingWithOptions
      launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
  FirebaseApp.configure()
  GIDSignIn.sharedInstance().delegate = self
  return true
}

5. Identifiez les utilisateurs

Utiliser des règles pour restreindre aux utilisateurs authentifiés

Nous allons maintenant ajouter une règle pour exiger une authentification avant de lire ou d'écrire un message. Pour ce faire, nous ajoutons les règles suivantes à notre objet de données messages. Dans la section Base de données de la console Firebase, sélectionnez Base de données en temps réel, puis cliquez sur l'onglet Règles. Mettez ensuite à jour les règles pour qu'elles ressemblent à ceci :

{
  "rules": {
    "messages": {
      ".read": "auth != null",
      ".write": "auth != null"
    }
  }
}

Pour plus d'informations sur la façon dont cela fonctionne (y compris la documentation sur la variable "auth"), consultez la documentation de sécurité Firebase.

Configurer les API d'authentification

Avant que votre application puisse accéder aux API d'authentification Firebase au nom de vos utilisateurs, vous devrez l'activer

  1. Accédez à la console Firebase et sélectionnez votre projet
  2. Sélectionnez Authentification
  3. Sélectionnez l'onglet Méthode de connexion
  4. Basculez le commutateur Google sur activé (bleu)
  5. Appuyez sur Enregistrer dans la boîte de dialogue résultante

Si vous obtenez des erreurs plus tard dans cet atelier de programmation avec le message "CONFIGURATION_NOT_FOUND", revenez à cette étape et vérifiez votre travail.

Confirmer la dépendance de Firebase Auth

Vérifiez que les dépendances Firebase Auth existent dans le fichier Podfile .

Fichier de pod

pod 'Firebase/Auth'

Configurez votre Info.plist pour la connexion Google.

Vous devrez ajouter un schéma d'URL personnalisé à votre projet XCode.

  1. Ouvrez la configuration de votre projet : double-cliquez sur le nom du projet dans l'arborescence de gauche. Sélectionnez votre application dans la section CIBLES, puis sélectionnez l'onglet Informations et développez la section Types d'URL.
  2. Cliquez sur le bouton + et ajoutez un schéma d'URL pour votre ID client inversé. Pour trouver cette valeur, ouvrez le fichier de configuration GoogleService-Info.plist et recherchez la clé REVERSED_CLIENT_ID. Copiez la valeur de cette clé et collez-la dans la zone Schémas d'URL de la page de configuration. Laissez les autres champs vides.
  3. Une fois terminée, votre configuration devrait ressembler à ce qui suit (mais avec les valeurs spécifiques à votre application) :

1b54d5bd2f4f1448.png

Définir l'ID client pour la connexion Google

Une fois Firebase configuré, nous pouvons utiliser le clientID pour configurer la connexion Google dans la méthode "didFinishLaunchingWithOptions:".

AppDelegate.swift

  func application(_ application: UIApplication, didFinishLaunchingWithOptions
      launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
  FirebaseApp.configure()
  GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
  GIDSignIn.sharedInstance().delegate = self
  return true
}

Ajouter le gestionnaire de connexion

Une fois le résultat de la connexion Google réussi, utilisez le compte pour vous authentifier auprès de Firebase.

AppDelegate.swift

  func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error?) {
    if let error = error {
      print("Error \(error)")
      return
    }

    guard let authentication = user.authentication else { return }
    let credential = GoogleAuthProvider.credential(withIDToken: authentication.idToken,
                                                      accessToken: authentication.accessToken)
    Auth.auth().signIn(with: credential) { (user, error) in
      if let error = error {
        print("Error \(error)")
        return
      }
    }
  }

Connectez automatiquement l’utilisateur. Ajoutez ensuite un écouteur à Firebase Auth, pour permettre à l'utilisateur d'accéder à l'application, après une connexion réussie. Et supprimez l'écouteur lors de la déinit.

SignInViewController.swift

  override func viewDidLoad() {
    super.viewDidLoad()
    GIDSignIn.sharedInstance().uiDelegate = self
    GIDSignIn.sharedInstance().signInSilently()
    handle = Auth.auth().addStateDidChangeListener() { (auth, user) in
      if user != nil {
        MeasurementHelper.sendLoginEvent()
        self.performSegue(withIdentifier: Constants.Segues.SignInToFp, sender: nil)
      }
    }
  }

  deinit {
    if let handle = handle {
      Auth.auth().removeStateDidChangeListener(handle)
    }
  }

Se déconnecter

Ajouter la méthode de déconnexion

FCViewController.swift

  @IBAction func signOut(_ sender: UIButton) {
    let firebaseAuth = Auth.auth()
    do {
      try firebaseAuth.signOut()
      dismiss(animated: true, completion: nil)
    } catch let signOutError as NSError {
      print ("Error signing out: \(signOutError.localizedDescription)")
    }
  }

Test de lecture des messages en tant qu'utilisateur connecté

  1. Clique le 98205811bbed9d74.png Bouton Exécuter .
  2. Vous devriez être immédiatement redirigé vers l’écran de connexion. Appuyez sur le bouton de connexion Google.
  3. Vous devriez alors être envoyé vers l’écran de messagerie si tout a bien fonctionné.

6. Activer la base de données en temps réel

2efe6805ef369641.png

Importer des messages

Dans votre projet dans la console Firebase , sélectionnez l'élément Base de données dans la barre de navigation de gauche. Dans le menu à débordement de la Base de données, sélectionnez Importer JSON . Accédez au fichier initial_messages.json dans le répertoire friendlychat, sélectionnez-le puis cliquez sur le bouton Importer . Cela remplacera toutes les données actuellement dans votre base de données. Vous pouvez également modifier la base de données directement, en utilisant le + vert et le x rouge pour ajouter et supprimer des éléments.

20ccf4856b715b4c.png

Après importation, votre base de données devrait ressembler à ceci :

f3e0367f1c9cd187.png

Confirmer la dépendance de la base de données Firebase

Dans le bloc de dépendances du fichier Podfile , confirmez que Firebase/Database est inclus.

Fichier de pod

pod 'Firebase/Database'

Synchroniser les messages existants

Ajoutez du code qui synchronise les messages nouvellement ajoutés avec l'interface utilisateur de l'application.

Le code que vous ajoutez dans cette section :

  • Initialisez la base de données Firebase et ajoutez un écouteur pour gérer les modifications apportées à la base de données.
  • Mettez à jour le DataSnapshot afin que les nouveaux messages soient affichés.

Modifiez les méthodes "deinit", "configureDatabase" et "tableView:cellForRow indexPath:" de votre FCViewController ; remplacer par le code défini ci-dessous :

FCViewController.swift

  deinit {
    if let refHandle = _refHandle {
      self.ref.child("messages").removeObserver(withHandle: _refHandle)
    }
  }


  func configureDatabase() {
    ref = Database.database().reference()
    // Listen for new messages in the Firebase database
    _refHandle = self.ref.child("messages").observe(.childAdded, with: { [weak self] (snapshot) -> Void in
      guard let strongSelf = self else { return }
      strongSelf.messages.append(snapshot)
      strongSelf.clientTable.insertRows(at: [IndexPath(row: strongSelf.messages.count-1, section: 0)], with: .automatic)
    })
  }


  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    // Dequeue cell
    let cell = self.clientTable.dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath)
    // Unpack message from Firebase DataSnapshot
    let messageSnapshot = self.messages[indexPath.row]
    guard let message = messageSnapshot.value as? [String: String] else { return cell }
    let name = message[Constants.MessageFields.name] ?? ""
    let text = message[Constants.MessageFields.text] ?? ""
    cell.textLabel?.text = name + ": " + text
    cell.imageView?.image = UIImage(named: "ic_account_circle")
    if let photoURL = message[Constants.MessageFields.photoURL], let URL = URL(string: photoURL),
        let data = try? Data(contentsOf: URL) {
      cell.imageView?.image = UIImage(data: data)
    }
    return cell
  }

Tester la synchronisation des messages

  1. Clique le 98205811bbed9d74.png Bouton Exécuter .
  2. Cliquez sur le bouton Se connecter pour commencer pour accéder à la fenêtre des messages.
  3. Ajoutez de nouveaux messages directement dans la console Firebase en cliquant sur le symbole vert + à côté de l'entrée "messages" et en ajoutant un objet comme celui-ci : f9876ffc8b316b14.png
  4. Confirmez qu'ils apparaissent dans l'interface utilisateur de Friendly-Chat.

7. Envoyer des messages

Implémenter Envoyer un message

Transférez les valeurs vers la base de données. Lorsque vous utilisez la méthode push pour ajouter des données à la base de données Firebase Realtime, un identifiant automatique sera ajouté. Ces identifiants générés automatiquement sont séquentiels, ce qui garantit que les nouveaux messages seront ajoutés dans le bon ordre.

Modifiez la méthode « sendMessage: » de votre FCViewController ; remplacer par le code défini ci-dessous :

FCViewController.swift

  func sendMessage(withData data: [String: String]) {
    var mdata = data
    mdata[Constants.MessageFields.name] = Auth.auth().currentUser?.displayName
    if let photoURL = Auth.auth().currentUser?.photoURL {
      mdata[Constants.MessageFields.photoURL] = photoURL.absoluteString
    }

    // Push data to Firebase Database
    self.ref.child("messages").childByAutoId().setValue(mdata)
  }

Tester l'envoi de messages

  1. Clique le 98205811bbed9d74.png Bouton Exécuter .
  2. Cliquez sur Connexion pour accéder à la fenêtre des messages.
  3. Tapez un message et appuyez sur Envoyer. Le nouveau message doit être visible dans l'interface utilisateur de l'application et dans la console Firebase.

8. Stocker et recevoir des images

Confirmer la dépendance du stockage Firebase

Dans le bloc de dépendances du Podfile , confirmez Firebase/Storage est inclus.

Fichier de pod

pod 'Firebase/Storage'

Activer Firebase Storage dans le tableau de bord

Accédez à la console Firebase et confirmez que le stockage est activé avec le domaine "gs://PROJECTID.appspot.com".

b0438b37a588bcee.png

Si vous voyez plutôt la fenêtre d'activation, cliquez sur « COMMENCER » pour l'activer avec les règles par défaut.

c290bbebff2cafa7.png

Configurer FirebaseStorage

FCViewController.swift

  func configureStorage() {
    storageRef = Storage.storage().reference()
  }

Recevoir des images dans les messages existants

Ajoutez du code qui télécharge les images depuis Firebase Storage.

Modifiez la méthode "tableView: cellForRowAt indexPath:" de votre FCViewController ; remplacer par le code défini ci-dessous :

FCViewController.swift

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    // Dequeue cell
    let cell = self.clientTable .dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath)
    // Unpack message from Firebase DataSnapshot
    let messageSnapshot: DataSnapshot! = self.messages[indexPath.row]
    guard let message = messageSnapshot.value as? [String:String] else { return cell }
    let name = message[Constants.MessageFields.name] ?? ""
    if let imageURL = message[Constants.MessageFields.imageURL] {
      if imageURL.hasPrefix("gs://") {
        Storage.storage().reference(forURL: imageURL).getData(maxSize: INT64_MAX) {(data, error) in
          if let error = error {
            print("Error downloading: \(error)")
            return
          }
          DispatchQueue.main.async {
            cell.imageView?.image = UIImage.init(data: data!)
            cell.setNeedsLayout()
          }
        }
      } else if let URL = URL(string: imageURL), let data = try? Data(contentsOf: URL) {
        cell.imageView?.image = UIImage.init(data: data)
      }
      cell.textLabel?.text = "sent by: \(name)"
    } else {
      let text = message[Constants.MessageFields.text] ?? ""
      cell.textLabel?.text = name + ": " + text
      cell.imageView?.image = UIImage(named: "ic_account_circle")
      if let photoURL = message[Constants.MessageFields.photoURL], let URL = URL(string: photoURL),
          let data = try? Data(contentsOf: URL) {
        cell.imageView?.image = UIImage(data: data)
      }
    }
    return cell
  }

9. Envoyer des messages image

Implémenter le stockage et l'envoi d'images

Téléchargez une image de l'utilisateur, puis synchronisez l'URL de stockage de cette image avec la base de données afin que cette image soit envoyée dans le message.

Modifiez la méthode « imagePickerController: didFinishPickingMediaWithInfo: » de votre FCViewController ; remplacer par le code défini ci-dessous :

FCViewController.swift

  func imagePickerController(_ picker: UIImagePickerController,
    didFinishPickingMediaWithInfo info: [String : Any]) {
      picker.dismiss(animated: true, completion:nil)
    guard let uid = Auth.auth().currentUser?.uid else { return }

    // if it's a photo from the library, not an image from the camera
    if #available(iOS 8.0, *), let referenceURL = info[UIImagePickerControllerReferenceURL] as? URL {
      let assets = PHAsset.fetchAssets(withALAssetURLs: [referenceURL], options: nil)
      let asset = assets.firstObject
      asset?.requestContentEditingInput(with: nil, completionHandler: { [weak self] (contentEditingInput, info) in
        let imageFile = contentEditingInput?.fullSizeImageURL
        let filePath = "\(uid)/\(Int(Date.timeIntervalSinceReferenceDate * 1000))/\((referenceURL as AnyObject).lastPathComponent!)"
        guard let strongSelf = self else { return }
        strongSelf.storageRef.child(filePath)
          .putFile(from: imageFile!, metadata: nil) { (metadata, error) in
            if let error = error {
              let nsError = error as NSError
              print("Error uploading: \(nsError.localizedDescription)")
              return
            }
            strongSelf.sendMessage(withData: [Constants.MessageFields.imageURL: strongSelf.storageRef.child((metadata?.path)!).description])
          }
      })
    } else {
      guard let image = info[UIImagePickerControllerOriginalImage] as? UIImage else { return }
      let imageData = UIImageJPEGRepresentation(image, 0.8)
      let imagePath = "\(uid)/\(Int(Date.timeIntervalSinceReferenceDate * 1000)).jpg"
      let metadata = StorageMetadata()
      metadata.contentType = "image/jpeg"
      self.storageRef.child(imagePath)
        .putData(imageData!, metadata: metadata) { [weak self] (metadata, error) in
          if let error = error {
            print("Error uploading: \(error)")
            return
          }
          guard let strongSelf = self else { return }
          strongSelf.sendMessage(withData: [Constants.MessageFields.imageURL: strongSelf.storageRef.child((metadata?.path)!).description])
      }
    }
  }

Tester l'envoi et la réception de messages image

  1. Clique le 98205811bbed9d74.png Bouton Exécuter .
  2. Cliquez sur Connexion pour accéder à la fenêtre des messages.
  3. Cliquez sur l'icône « ajouter une photo » pour choisir une photo. Le nouveau message avec la photo doit être visible dans l'interface utilisateur de l'application et dans la console Firebase.

10. Félicitations !

Vous avez utilisé Firebase pour créer facilement une application de chat en temps réel.

Ce que nous avons couvert

  • Base de données en temps réel
  • Connexion fédérée
  • Stockage

Apprendre encore plus