Firebase iOS Codelab Swift

1. Panoramica

2efe6805ef369641.png

Ti diamo il benvenuto nel codelab Friendly Chat. In questo codelab imparerai a utilizzare la piattaforma Firebase per creare applicazioni per iOS. Implementerai un client di chat e ne monitorerai il rendimento utilizzando Firebase.

Cosa imparerai a fare

  • Consenti agli utenti di accedere.
  • Sincronizza i dati utilizzando Firebase Realtime Database.
  • Archiviare file binari in Firebase Storage.

Che cosa ti serve

  • Xcode
  • CocoaPods
  • Un dispositivo di test con iOS 8.0 o versioni successive o un simulatore

Come utilizzerai questo tutorial?

Leggilo e basta Leggilo e completa gli esercizi

Come valuteresti la tua esperienza di creazione di app per iOS?

Principiante Intermedio Avanzato

2. recupera il codice campione

Clona il repository GitHub dalla riga di comando.

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

3. Crea l'app iniziale

2f4c98d858c453fe.png

Per creare l'app iniziale:

  1. In una finestra del terminale, vai alla directory android_studio_folder.pngios-starter/swift-starter dal download del codice campione.
  2. Esegui pod install --repo-update
  3. Apri il file FriendlyChatSwift.xcworkspace per aprire il progetto in Xcode.
  4. Fai clic sul pulsante 98205811bbed9d74.pngEsegui.

Dopo qualche secondo dovrebbe apparire la schermata Home di Friendly Chat. Dovrebbe apparire l'interfaccia utente. Tuttavia, a questo punto non puoi accedere, inviare o ricevere messaggi. L'app verrà interrotta con un'eccezione finché non completi il passaggio successivo.

4. Configura un progetto Firebase

Crea un nuovo progetto Firebase

  1. Accedi alla console Firebase utilizzando il tuo Account Google.
  2. Fai clic sul pulsante per creare un nuovo progetto, quindi inserisci un nome per il progetto (ad esempio FriendlyChat).
  3. Fai clic su Continua.
  4. Se richiesto, leggi e accetta i termini di Firebase, quindi fai clic su Continua.
  5. (Facoltativo) Attiva l'assistenza AI nella console Firebase (denominata "Gemini in Firebase").
  6. Per questo codelab non hai bisogno di Google Analytics, quindi disattiva l'opzione Google Analytics.
  7. Fai clic su Crea progetto, attendi il provisioning del progetto, poi fai clic su Continua.

Esegui l'upgrade del piano tariffario Firebase

Per utilizzare Cloud Storage for Firebase, il tuo progetto Firebase deve essere incluso nel piano tariffario con pagamento a consumo (Blaze), il che significa che è collegato a un account di fatturazione Cloud.

  • Un account di fatturazione Cloud richiede un metodo di pagamento, ad esempio una carta di credito.
  • Se non hai mai utilizzato Firebase e Google Cloud, verifica se hai diritto a un credito di 300$e a un account Cloud Billing di prova senza costi.
  • Se stai svolgendo questo codelab nell'ambito di un evento, chiedi all'organizzatore se sono disponibili crediti Cloud.

Per eseguire l'upgrade del progetto al piano Blaze:

  1. Nella console Firebase, seleziona l'opzione per eseguire l'upgrade del piano.
  2. Seleziona il piano Blaze. Segui le istruzioni sullo schermo per collegare un account di fatturazione Cloud al tuo progetto.
    Se hai dovuto creare un account di fatturazione Cloud nell'ambito di questo upgrade, potresti dover tornare al flusso di upgrade nella console Firebase per completarlo.

Collegare l'app per iOS

  1. Nella schermata Panoramica del progetto del nuovo progetto, fai clic su Aggiungi Firebase alla tua app per iOS.
  2. Inserisci l'ID bundle come "com.google.firebase.codelab.FriendlyChatSwift".
  3. Inserisci l'ID App Store come "123456".
  4. Fai clic su Registra app.

Aggiungere il file GoogleService-Info.plist all'app

Nella seconda schermata, fai clic su Scarica GoogleService-Info.plist per scaricare un file di configurazione che contiene tutti i metadati Firebase necessari per la tua app. Copia il file nell'applicazione e aggiungilo al target FriendlyChatSwift.

Ora puoi fare clic sulla "x" nell'angolo in alto a destra del popup per chiuderlo, saltando i passaggi 3 e 4, perché li eseguirai qui.

19d59efb213ddbdc.png

Importa il modulo Firebase

Inizia assicurandoti che il modulo Firebase sia importato.

AppDelegate.swift, FCViewController.swift

import Firebase

Configura Firebase in AppDelegate

Utilizza il metodo "configure" in FirebaseApp all'interno della funzione application:didFinishLaunchingWithOptions per configurare i servizi Firebase sottostanti dal file .plist.

AppDelegate.swift

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

5. Identificare gli utenti

Utilizzare le regole per limitare l'accesso agli utenti autenticati

Ora aggiungeremo una regola per richiedere l'autenticazione prima di leggere o scrivere qualsiasi messaggio. A questo scopo, aggiungiamo le seguenti regole all'oggetto dati dei messaggi. Nella sezione Database della console Firebase, seleziona Realtime Database e poi fai clic sulla scheda Regole. Poi aggiorna le regole in modo che abbiano questo aspetto:

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

Per ulteriori informazioni su come funziona (inclusa la documentazione sulla variabile "auth"), consulta la documentazione sulla sicurezza di Firebase.

Configura le API di autenticazione

Prima che la tua applicazione possa accedere alle API Firebase Authentication per conto dei tuoi utenti, devi abilitarla

  1. Vai alla console Firebase e seleziona il tuo progetto.
  2. Seleziona Autenticazione.
  3. Seleziona la scheda Metodo di accesso.
  4. Attiva l'opzione Google (blu).
  5. Fai clic su Salva nella finestra di dialogo risultante.

Se in un secondo momento in questo codelab ricevi errori con il messaggio "CONFIGURATION_NOT_FOUND", torna a questo passaggio e ricontrolla il tuo lavoro.

Conferma la dipendenza di Firebase Auth

Verifica che le dipendenze di Firebase Auth esistano nel file Podfile.

Podfile

pod 'Firebase/Auth'

Configura il file Info.plist per Accedi con Google.

Dovrai aggiungere uno schema URL personalizzato al tuo progetto XCode.

  1. Apri la configurazione del progetto: fai doppio clic sul nome del progetto nella visualizzazione ad albero a sinistra. Seleziona l'app dalla sezione TARGET, poi seleziona la scheda Informazioni ed espandi la sezione Tipi di URL.
  2. Fai clic sul pulsante + e aggiungi uno schema URL per l'ID client invertito. Per trovare questo valore, apri il file di configurazione GoogleService-Info.plist e cerca la chiave REVERSED_CLIENT_ID. Copia il valore della chiave e incollalo nella casella Schemi URL della pagina di configurazione. Lascia vuoti gli altri campi.
  3. Al termine, la configurazione dovrebbe essere simile alla seguente (ma con i valori specifici dell'applicazione):

1b54d5bd2f4f1448.png

Imposta clientID per Accedi con Google

Una volta configurato Firebase, possiamo utilizzare il clientID per configurare l'accesso con Google all'interno del metodo "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
}

Aggiungere il gestore di accesso

Una volta che l'accesso con Google è andato a buon fine, utilizza l'account per l'autenticazione con 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
      }
    }
  }

Consentire l'accesso automatico all'utente. Poi aggiungi un listener a Firebase Auth per consentire all'utente di accedere all'app dopo l'accesso. e rimuovi il listener su 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)
    }
  }

Esci

Aggiungere il metodo di disconnessione

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)")
    }
  }

Testare la lettura dei messaggi come utente che ha eseguito l'accesso

  1. Fai clic sul pulsante 98205811bbed9d74.pngEsegui.
  2. Dovresti essere reindirizzato immediatamente alla schermata di accesso. Tocca il pulsante Accedi con Google.
  3. Se tutto ha funzionato correttamente, dovresti essere reindirizzato alla schermata di messaggistica.

6. Attivare Realtime Database

2efe6805ef369641.png

Importare i messaggi

Nel tuo progetto nella console Firebase, seleziona l'elemento Database nella barra di navigazione a sinistra. Nel menu extra del database, seleziona Importa JSON. Vai al file initial_messages.json nella directory friendlychat, selezionalo e fai clic sul pulsante Importa. Verranno sostituiti tutti i dati attualmente presenti nel database. Puoi anche modificare direttamente il database utilizzando il segno + verde e la x rossa per aggiungere e rimuovere elementi.

20ccf4856b715b4c.png

Dopo l'importazione, il database dovrebbe avere il seguente aspetto:

f3e0367f1c9cd187.png

Conferma la dipendenza dal database Firebase

Nel blocco delle dipendenze del file Podfile, verifica che Firebase/Database sia incluso.

Podfile

pod 'Firebase/Database'

Sincronizzare i messaggi esistenti

Aggiungi il codice che sincronizza i messaggi appena aggiunti all'interfaccia utente dell'app.

Il codice che aggiungi in questa sezione:

  • Inizializza il database Firebase e aggiungi un listener per gestire le modifiche apportate al database.
  • Aggiorna DataSnapshot in modo che vengano visualizzati i nuovi messaggi.

Modifica i metodi "deinit", "configureDatabase" e "tableView:cellForRow indexPath:" di FCViewController; sostituiscili con il codice definito di seguito:

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
  }

Testare la sincronizzazione dei messaggi

  1. Fai clic sul pulsante 98205811bbed9d74.pngEsegui.
  2. Fai clic sul pulsante Accedi per iniziare per andare alla finestra dei messaggi.
  3. Aggiungi nuovi messaggi direttamente nella console Firebase facendo clic sul simbolo + verde accanto alla voce "messaggi" e aggiungendo un oggetto come il seguente: f9876ffc8b316b14.png
  4. Verifica che vengano visualizzati nell'interfaccia utente di Friendly-Chat.

7. Invio messaggi

Implementare Invia messaggio

Effettua il push dei valori nel database. Quando utilizzi il metodo push per aggiungere dati a Firebase Realtime Database, viene aggiunto un ID automatico. Questi ID generati automaticamente sono sequenziali, il che garantisce che i nuovi messaggi vengano aggiunti nell'ordine corretto.

Modifica il metodo "sendMessage:" di FCViewController; sostituiscilo con il codice definito di seguito:

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)
  }

Testare l'invio di messaggi

  1. Fai clic sul pulsante 98205811bbed9d74.pngEsegui.
  2. Fai clic su Accedi per andare alla finestra dei messaggi.
  3. Digita un messaggio e premi Invia. Il nuovo messaggio dovrebbe essere visibile nell'UI dell'app e nella console Firebase.

8. Archiviare e ricevere immagini

Conferma la dipendenza di Firebase Storage

Nel blocco delle dipendenze di Podfile, verifica che Firebase/Storage sia incluso.

Podfile

pod 'Firebase/Storage'

Configurare Cloud Storage for Firebase

Ecco come configurare Cloud Storage for Firebase nel tuo progetto Firebase:

  1. Nel riquadro a sinistra della console Firebase, espandi Build e seleziona Storage.
  2. Fai clic su Inizia.
  3. Seleziona una posizione per il bucket di archiviazione predefinito.
    I bucket in US-WEST1, US-CENTRAL1 e US-EAST1 possono usufruire del livello"Sempre senza costi" per Google Cloud Storage. I bucket in tutte le altre località seguono i prezzi e l'utilizzo di Google Cloud Storage.
  4. Fai clic su Avvia in modalità di test. Leggi l'esclusione di responsabilità relativa alle regole di sicurezza.
    Più avanti in questo codelab, aggiungerai regole di sicurezza per proteggere i tuoi dati. Nondistribuire o esporre pubblicamente un'app senza aggiungere regole di sicurezza per il bucket Storage.
  5. Fai clic su Crea.

Configura FirebaseStorage

FCViewController.swift

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

Ricevere immagini nei messaggi esistenti

Aggiungi il codice che scarica le immagini da Firebase Storage.

Modifica il metodo "tableView: cellForRowAt indexPath:" di FCViewController; sostituiscilo con il codice definito di seguito:

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. Invio di messaggi con immagini

Implementare Store and Send Images

Carica un'immagine dall'utente, quindi sincronizza l'URL di archiviazione di questa immagine con il database in modo che venga inviata all'interno del messaggio.

Modifica il metodo "imagePickerController: didFinishPickingMediaWithInfo:" di FCViewController; sostituiscilo con il codice definito di seguito:

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])
      }
    }
  }

Testare l'invio e la ricezione di messaggi illustrati

  1. Fai clic sul pulsante 98205811bbed9d74.pngEsegui.
  2. Fai clic su Accedi per andare alla finestra dei messaggi.
  3. Fai clic sull'icona "Aggiungi una foto" per selezionarne una. Il nuovo messaggio con la foto dovrebbe essere visibile nell'interfaccia utente dell'app e nella console Firebase.

10. Complimenti!

Hai utilizzato Firebase per creare facilmente un'applicazione di chat in tempo reale.

Argomenti trattati

  • Realtime Database
  • Accesso federato
  • Archiviazione

Scopri di più