1. Panoramica
Ti diamo il benvenuto nel codelab di 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?
Come valuteresti la tua esperienza con la creazione di app per iOS?
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
Per creare l'app iniziale:
- In una finestra del terminale, vai alla directory
ios-starter/swift-starter
del download del codice di esempio - Esegui
pod install --repo-update
- Apri il file FriendlyChatSwift.xcworkspace per aprire il progetto in Xcode.
- Fai clic sul pulsante Esegui.
Dopo alcuni secondi dovresti visualizzare la schermata Home di Chat dal vivo. 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. Creare un progetto nella Console Firebase
Creare un progetto
Nella Console Firebase, seleziona Aggiungi progetto.
Assegna al progetto il nome FriendlyChat
, quindi fai clic su Crea progetto.
Eseguire l'upgrade del piano tariffario di Firebase
Per utilizzare Cloud Storage for Firebase, il progetto Firebase deve utilizzare il piano tariffario Blaze (pagamento a consumo), il che significa che deve essere 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, controlla se hai l'idoneità a ricevere un credito di 300$e un account di fatturazione Cloud per la 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:
- Nella console Firebase, seleziona l'upgrade del piano.
- 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
- Nella schermata Panoramica del progetto del nuovo progetto, fai clic su Aggiungi Firebase alla tua app per iOS.
- Inserisci l'ID pacchetto, ad esempio "
com.google.firebase.codelab.FriendlyChatSwift
". - Inserisci l'ID App Store come "
123456
". - 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 contenente tutti i metadati Firebase necessari per la tua app. Copia il file nella tua 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, poiché li eseguirai qui.
Importa il modulo Firebase
Per prima cosa, assicurati 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 messaggi. Per farlo, 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 il seguente 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.
Configurare le API di autenticazione
Prima che la tua applicazione possa accedere alle API di autenticazione di Firebase per conto dei tuoi utenti, devi attivarla
- Vai alla console Firebase e seleziona il tuo progetto.
- Seleziona Authentication (Autenticazione).
- Seleziona la scheda Metodo di accesso.
- Imposta l'opzione Google su Abilitato (blu)
- Fai clic su Salva nella finestra di dialogo visualizzata.
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 da 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.
- Apri la configurazione del progetto: fai doppio clic sul nome del progetto nella visualizzazione ad albero a sinistra. Seleziona la tua app dalla sezione TARGET, poi seleziona la scheda Informazioni ed espandi la sezione Tipi di URL.
- Fai clic sul pulsante Più 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.
- Al termine, la configurazione dovrebbe avere un aspetto simile al seguente (ma con i valori specifici dell'applicazione):
Impostare 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 dell'accesso
Una volta che il risultato dell'accesso con Google è stato positivo, utilizza l'account per autenticarti 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. Aggiungi poi un ascoltatore ad Auth Firebase per consentire all'utente di accedere all'app dopo l'accesso riuscito. E rimuovi l'ascoltatore al termine dell'inizializzazione.
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
Aggiungi il metodo di uscita
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
- Fai clic sul pulsante Esegui.
- Dovresti essere reindirizzato immediatamente alla schermata di accesso. Tocca il pulsante di accesso con Google.
- Se tutto ha funzionato correttamente, dovresti essere reindirizzato alla schermata della messaggistica.
6. Attivare Realtime Database
Importare Messaggi
Nel progetto della 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 di 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 Più verde e la X rossa per aggiungere e rimuovere elementi.
Dopo l'importazione, il database dovrebbe avere il seguente aspetto:
Confermare la dipendenza dal database Firebase
Nel blocco delle dipendenze del file Podfile
, verifica che sia incluso Firebase/Database
.
Podfile
pod 'Firebase/Database'
Sincronizzare i messaggi esistenti
Aggiungi il codice che sincronizza i messaggi appena aggiunti con l'interfaccia utente dell'app.
Il codice che aggiungi in questa sezione:
- Inizializza il database Firebase e aggiungi un ascoltatore 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
- Fai clic sul pulsante Esegui.
- Fai clic sul pulsante Accedi per iniziare per aprire la finestra dei messaggi.
- Aggiungi nuovi messaggi direttamente nella Console Firebase facendo clic sul simbolo + verde accanto alla voce "messages" e aggiungendo un oggetto come il seguente:
- Verifica che vengano visualizzati nell'interfaccia utente di Chat dal vivo.
7. Invio messaggi
Implementa Invia messaggio
Invia i valori al 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
- Fai clic sul pulsante Esegui.
- Fai clic su Accedi per aprire la finestra dei messaggi.
- Digita un messaggio e premi Invia. Il nuovo messaggio dovrebbe essere visibile nell'interfaccia utente dell'app e nella Console Firebase.
8. Archivia e ricevi immagini
Conferma dipendenza da 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:
- Nel riquadro a sinistra della console Firebase, espandi Build e seleziona Archiviazione.
- Fai clic su Inizia.
- Seleziona una posizione per il bucket di archiviazione predefinito.
I bucket inUS-WEST1
,US-CENTRAL1
eUS-EAST1
possono usufruire del livello"Sempre senza costi" per Google Cloud Storage. I bucket in tutte le altre località rispettano i prezzi e l'utilizzo di Google Cloud Storage. - Fai clic su Avvia in modalità di test. Leggi il disclaimer relativo alle regole di sicurezza.
Più avanti in questo codelab, aggiungerai regole di sicurezza per proteggere i tuoi dati. Non distribuire o esporre un'app pubblicamente senza aggiungere regole di sicurezza per il bucket di archiviazione. - 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:" del tuo 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. Inviare messaggi con immagini
Implementare Immagini archiviate e inviate
Carica un'immagine dall'utente, quindi sincronizza l'URL di archiviazione dell'immagine con il database in modo che venga inviata all'interno del messaggio.
Modifica il metodo "imagePickerController: didFinishPickingMediaWithInfo:" del tuo 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 con immagini
- Fai clic sul pulsante Esegui.
- Fai clic su Accedi per aprire la finestra dei messaggi.
- Fai clic sull'icona "Aggiungi una foto" per sceglierne 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