1. Présentation
Bienvenue dans l'atelier de programmation sur le chat convivial. Dans cet atelier de programmation, vous allez apprendre à utiliser la plate-forme Firebase pour créer des applications iOS. Vous allez implémenter un client de chat et surveiller ses performances à l'aide de Firebase.
Points abordés
- Autorisez les utilisateurs à se connecter.
- Synchroniser des données à l'aide de Firebase Realtime Database
- Stockez des fichiers binaires dans Firebase Storage.
Prérequis
- Xcode
- CocoaPods
- Un appareil de test équipé d'iOS 8.0 ou version ultérieure, ou un simulateur
Comment allez-vous utiliser ce tutoriel ?
Comment évalueriez-vous votre niveau en matière de création d'applications iOS ?
2. Obtenir l'exemple de code
Clonez le dépôt GitHub à partir de la ligne de commande.
$ git clone https://github.com/firebase/codelab-friendlychat-ios
3. Compiler l'application de démarrage
Pour compiler l'application de démarrage :
- Dans une fenêtre de terminal, accédez au répertoire
ios-starter/swift-starter
à partir de l'exemple de code téléchargé. - Exécuter
pod install --repo-update
- Ouvrez le fichier FriendlyChatSwift.xcworkspace pour ouvrir le projet dans Xcode.
- Cliquez sur le bouton Run (Exécuter).
L'écran d'accueil de Friendly Chat devrait s'afficher au bout de quelques secondes. L'interface utilisateur doit s'afficher. Toutefois, à ce stade, vous ne pouvez plus vous connecter, ni envoyer ni recevoir de messages. L'application s'arrête avec une exception jusqu'à ce que vous passiez à l'étape suivante.
4. Créer un projet dans la console Firebase
Créer un projet
Dans la console Firebase, sélectionnez Ajouter un projet.
Appelez le projet FriendlyChat
, puis cliquez sur Créer un projet.
Changer de forfait Firebase
Pour que vous puissiez utiliser Cloud Storage for Firebase, votre projet Firebase doit bénéficier du forfait avec paiement à l'usage (Blaze), ce qui signifie qu'il est associé à un compte de facturation Cloud.
- Un compte de facturation Cloud nécessite un mode de paiement, comme une carte de crédit.
- Si vous débutez avec Firebase et Google Cloud, vérifiez si vous pouvez bénéficier d'un crédit de 300$et d'un compte de facturation Cloud avec essai sans frais.
- Si vous suivez cet atelier de programmation dans le cadre d'un événement, demandez à l'organisateur s'il existe des crédits Cloud disponibles.
Pour passer à la formule Blaze, procédez comme suit :
- Dans la console Firebase, sélectionnez l'option Mettre à niveau votre forfait.
- Sélectionnez la formule Blaze. Suivez les instructions à l'écran pour associer un compte de facturation Cloud à votre projet.
Si vous avez dû créer un compte de facturation Cloud dans le cadre de cette migration, vous devrez peut-être revenir au flux de migration dans la console Firebase pour la finaliser.
Associer votre application iOS
- Dans l'écran "Vue d'ensemble du projet" de votre nouveau projet, cliquez sur Ajouter Firebase à votre application iOS.
- Saisissez l'ID du bundle sous la forme "
com.google.firebase.codelab.FriendlyChatSwift
". - Saisissez "
123456
" comme ID App Store. - Cliquez sur Register App (Enregistrer l'application).
Ajouter 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 à votre application. Copiez ce fichier dans votre application et ajoutez-le à la cible FriendlyChatSwift.
Vous pouvez maintenant cliquer sur le "x" dans l'angle supérieur droit de la fenêtre pop-up pour la fermer. Si vous ignorez les étapes 3 et 4, c'est cette étape que vous effectuerez ici.
Importer un module Firebase
Commencez par vérifier que le module Firebase
est importé.
AppDelegate.swift et 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. Identifier les utilisateurs
Utiliser des règles pour se limiter aux utilisateurs authentifiés
Nous allons maintenant ajouter une règle qui exige une authentification avant de lire ou d'écrire des messages. Pour ce faire, nous ajoutons les règles suivantes à notre objet de données des messages. Dans la section "Base de données" de la console Firebase, sélectionnez Realtime Database, puis cliquez sur l'onglet "Règles". Modifiez ensuite les règles pour qu'elles se présentent comme suit :
{
"rules": {
"messages": {
".read": "auth != null",
".write": "auth != null"
}
}
}
Pour en savoir plus à ce sujet (y compris pour obtenir de la documentation sur la variable "auth"), consultez la documentation sur la sécurité de Firebase.
Configurer les API d'authentification
Avant que votre application puisse accéder aux API Firebase Authentication au nom de vos utilisateurs, vous devez les activer.
- Accédez à la console Firebase et sélectionnez votre projet.
- Sélectionnez Authentification.
- Sélectionnez l'onglet Mode de connexion.
- Activez le bouton Google (bleu).
- Cliquez sur Enregistrer dans la boîte de dialogue qui s'affiche.
Si vous recevez des erreurs avec le message "CONFIGURATION_NOT_FOUND" dans la suite de cet atelier de programmation, revenez à cette étape et vérifiez votre travail.
Confirmer la dépendance Firebase Auth
Vérifiez que les dépendances Firebase Auth existent dans le fichier Podfile
.
Fichier de pod
pod 'Firebase/Auth'
Configurez votre fichier Info.plist pour Google Sign-In.
Vous devez ajouter un schéma d'URL personnalisé à votre projet XCode.
- 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 cliquez sur l'onglet "Infos" et développez la section "Types d'URL".
- Cliquez sur le bouton +, puis 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é, puis collez-la dans le champ "URL Schemes" (Formats d'URL) de la page de configuration. Laissez les autres champs vides.
- Une fois terminée, votre configuration devrait se présenter comme suit (mais avec vos valeurs spécifiques à l'application) :
Définir l'ID client pour Google Sign-In
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 Google Sign-In terminé, 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
}
}
}
Connecter l'utilisateur automatiquement. Ajoutez ensuite un écouteur à Firebase Auth pour autoriser l'utilisateur à accéder à l'application une fois la connexion établie. et supprimer l'écouteur sur "DEinit".
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)")
}
}
Tester la lecture des messages en tant qu'utilisateur connecté
- Cliquez sur le bouton Run (Exécuter).
- Vous devriez être immédiatement redirigé vers l'écran de connexion. Appuyez sur le bouton Google Sign-In.
- Si tout fonctionne correctement, vous devriez être redirigé vers l'écran de messagerie.
6. Activer Realtime Database
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évelopper de la base de données, sélectionnez Importer les données au format JSON. Accédez au fichier initial_messages.json
dans le répertoire friendlychat, sélectionnez-le, puis cliquez sur le bouton Importer. Toutes les données actuellement présentes dans votre base de données seront remplacées. Vous pouvez également modifier directement la base de données à l'aide du signe + vert et du signe x rouge pour ajouter et supprimer des éléments.
Une fois la base de données importée, elle doit se présenter comme suit :
Confirmer la dépendance de la base de données Firebase
Dans le bloc de dépendances du fichier Podfile
, vérifiez que Firebase/Database
est inclus.
Podfile
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
DataSnapshot
pour afficher les nouveaux messages.
Modifiez les méthodes "deinit", "configureDatabase" et "tableView:cellForRow indexPath:" de votre FCViewController. Remplacez-les 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
- Cliquez sur le bouton Exécuter.
- Cliquez sur le bouton Se connecter pour commencer pour accéder à la fenêtre de messages.
- Ajoutez des messages directement dans la console Firebase en cliquant sur le symbole + vert à côté de l'entrée "messages" et en ajoutant un objet semblable à celui-ci:
- Vérifiez qu'ils s'affichent dans l'interface utilisateur de Friendly Chat.
7. Envoyer des messages
Implémenter Send Message
Transférez les valeurs vers la base de données. Lorsque vous utilisez la méthode push pour ajouter des données à Firebase Realtime Database, un ID automatique est ajouté. Ces ID générés automatiquement sont séquentiels, ce qui garantit que les nouveaux messages seront ajoutés dans l'ordre correct.
Modifiez la méthode "sendMessage:" de votre FCViewController. Remplacez-la 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
- Cliquez sur le bouton Run (Exécuter).
- Cliquez sur Sign In (Connexion) pour accéder à la fenêtre des messages.
- Saisissez un message, puis appuyez sur Envoyer. Le nouveau message devrait être visible dans l'UI de l'application et dans la console Firebase.
8. Stocker et recevoir des images
Confirmer la dépendance Firebase Storage
Dans le bloc de dépendances de Podfile
, vérifiez que Firebase/Storage
est inclus.
Podfile
pod 'Firebase/Storage'
Configurer Cloud Storage for Firebase
Voici comment configurer Cloud Storage for Firebase dans votre projet Firebase:
- Dans le panneau de gauche de la console Firebase, développez Build (Compilation), puis sélectionnez Storage (Stockage).
- Cliquez sur Commencer.
- Sélectionnez un emplacement pour votre bucket de stockage par défaut.
Les buckets deUS-WEST1
,US-CENTRAL1
etUS-EAST1
peuvent bénéficier du niveau "Toujours sans frais" pour Google Cloud Storage. Les buckets de tous les autres emplacements sont soumis aux tarifs et à l'utilisation de Google Cloud Storage. - Cliquez sur Démarrer en mode test. Lisez la clause de non-responsabilité concernant les règles de sécurité.
Dans la suite de cet atelier de programmation, vous ajouterez des règles de sécurité pour sécuriser vos données. Ne distribuez pas ni n'exposez pas publiquement une application sans ajouter de règles de sécurité à votre bucket Storage. - Cliquez sur Créer.
Configurer Firebase Storage
FCViewController.swift
func configureStorage() {
storageRef = Storage.storage().reference()
}
Recevoir des images dans des messages existants
Ajoutez du code qui télécharge les images à partir de Firebase Storage.
Modifiez la méthode "tableView: cellForRowAt indexPath:" de votre FCViewController. Remplacez-la 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
Importez une image à partir de l'utilisateur, puis synchronisez l'URL de stockage de cette image avec la base de données afin qu'elle soit envoyée dans le message.
Modifiez la méthode "imagePickerController: didFinishPickingMediaWithInfo:" de votre FCViewController, en la remplaçant 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 avec image
- Cliquez sur le bouton Exécuter.
- Cliquez sur Se connecter pour accéder à la fenêtre de messages.
- Cliquez sur l'icône "Ajouter une photo" pour choisir une photo. Le nouveau message contenant 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.
Points abordés
- Realtime Database
- Connexion fédérée
- Stockage