Firebase iOS Codelab Swift

1. Información general

2efe6805ef369641.png

Bienvenido al codelab de Friendly Chat. En este laboratorio de código, aprenderá a usar la plataforma Firebase para crear aplicaciones iOS. Implementarás un cliente de chat y monitorearás su desempeño usando Firebase.

Este codelab también está disponible en Objective-C.

Lo que aprenderás

  • Permitir que los usuarios inicien sesión.
  • Sincroniza datos con Firebase Realtime Database.
  • Almacena archivos binarios en Firebase Storage.

Lo que necesitarás

  • Xcode
  • CocoaPods
  • Un dispositivo de prueba con iOS 8.0+ o simulador

¿Cómo usarás este tutorial?

Léelo solo Léelo y completa los ejercicios.

¿Cómo calificaría su experiencia con la creación de aplicaciones para iOS?

Principiante Intermedio Competente

2. Obtén el código de muestra

Clona el repositorio de GitHub desde la línea de comandos.

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

3. Cree la aplicación de inicio

2f4c98d858c453fe.png

Para crear la aplicación de inicio:

  1. En una ventana de terminal, navegue hasta el android_studio_folder.png ios-starter/swift-starter directorio de su código de ejemplo descarga
  2. Ejecutar pod install --repo-update
  3. Abra el archivo FriendlyChatSwift.xcworkspace para abrir el proyecto en Xcode.
  4. Haga clic en el 98205811bbed9d74.png Botón Ejecutar.

Debería ver aparecer la pantalla de inicio de Friendly Chat después de unos segundos. Debería aparecer la interfaz de usuario. Sin embargo, en este punto no puede iniciar sesión, enviar ni recibir mensajes. La aplicación se cancelará con una excepción hasta que complete el siguiente paso.

4. Crea un proyecto de consola de Firebase

Crear proyecto

De Firebase consola seleccione Agregar proyecto.

Llamar el proyecto FriendlyChat , a continuación, haga clic en Crear proyecto.

Captura de pantalla de 2015-11-06 14: 13: 39.png

Conecta tu aplicación iOS

  1. En la pantalla de Proyecto Visión general del nuevo proyecto Agregar Firebase a su aplicación para iOS.
  2. Introduzca el ID de paquete, como " com.google.firebase.codelab.FriendlyChatSwift ".
  3. Entre el ID de tienda de aplicaciones como " 123456 ".
  4. Haga clic en Registro de aplicaciones.

Agregue el archivo GoogleService-Info.plist a su aplicación

En la segunda pantalla, haga clic Descargar GoogleService-Info.plist para descargar un archivo de configuración que contiene todos los metadatos Firebase necesario para su aplicación. Copiar el archivo a su aplicación y añadirla a la meta FriendlyChatSwift.

Ahora puede hacer clic en la "x" en la esquina superior derecha de la ventana emergente para cerrarla, omitiendo los pasos 3 y 4, ya que realizará esos pasos aquí.

19d59efb213ddbdc.png

Importar módulo de Firebase

Comience por asegurarse el Firebase módulo ha sido importada.

AppDelegate.swift , FCViewController.swift

import Firebase

Configurar Firebase en AppDelegate

Utilice el método "configure" en FirebaseApp dentro de la aplicación: función didFinishLaunchingWithOptions para configurar los servicios de Firebase subyacentes desde su archivo .plist.

AppDelegate.swift

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

5. Identificar usuarios

Utilice reglas para restringir a los usuarios autenticados

Ahora agregaremos una regla para requerir autenticación antes de leer o escribir cualquier mensaje. Para hacer esto, agregamos las siguientes reglas a nuestro objeto de datos de mensajes. Desde dentro de la sección Base de datos de la consola Firebase seleccionar en tiempo real de base de datos, a continuación, haga clic en la ficha Reglas. Luego actualice las reglas para que se vean así:

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

Para obtener más información sobre cómo funciona este (incluyendo documentación sobre la variable "auth") ver la base del fuego documentación de seguridad .

Configurar las API de autenticación

Antes de que su aplicación pueda acceder a las API de Firebase Authentication en nombre de sus usuarios, deberá habilitarla.

  1. Vaya a la consola de Firebase y seleccione su proyecto
  2. Seleccione autenticación
  3. Seleccione la pestaña En el Método sesión
  4. Activar el interruptor de Google al permitido (azul)
  5. Pulse Guardar en el cuadro de diálogo resultante

Si obtiene errores más adelante en este laboratorio de código con el mensaje "CONFIGURATION_NOT_FOUND", vuelva a este paso y vuelva a verificar su trabajo.

Confirma la dependencia de Firebase Auth

Existen dependencias Confirmar Firebase Auth en el Podfile archivo.

Podfile

pod 'Firebase/Auth'

Configure su Info.plist para el inicio de sesión de Google.

Deberá agregar un esquema de URL personalizado a su proyecto XCode.

  1. Abra la configuración de su proyecto: haga doble clic en el nombre del proyecto en la vista de árbol de la izquierda. Seleccione su aplicación en la sección OBJETIVOS, luego seleccione la pestaña Información y expanda la sección Tipos de URL.
  2. Haga clic en el botón + y agregue un esquema de URL para su ID de cliente invertido. Para encontrar este valor, abra el archivo de configuración GoogleService-Info.plist y busque la clave REVERSED_CLIENT_ID. Copie el valor de esa clave y péguelo en el cuadro Esquemas de URL en la página de configuración. Deje los otros campos en blanco.
  3. Cuando se complete, su configuración debería verse similar a la siguiente (pero con los valores específicos de su aplicación):

1b54d5bd2f4f1448.png

Establecer clientID para el inicio de sesión de Google

Una vez configurado Firebase, podemos usar el ID de cliente para configurar el inicio de sesión de Google dentro del método "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
}

Agregar el controlador de inicio de sesión

Una vez que el resultado del inicio de sesión de Google fue exitoso, use la cuenta para autenticarse 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
      }
    }
  }

Iniciar sesión automáticamente el usuario. Luego, agregue un oyente a Firebase Auth, para permitir que el usuario ingrese a la aplicación, después de iniciar sesión correctamente. Y elimine el oyente en 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)
    }
  }

Desconectar

Agregue el método de cierre de sesión

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

Prueba de lectura de mensajes como usuario que inició sesión

  1. Haga clic en el 98205811bbed9d74.png Botón Ejecutar.
  2. Debería ser enviado inmediatamente a la pantalla de inicio de sesión. Toque el botón Iniciar sesión con Google.
  3. Luego, debería ser enviado a la pantalla de mensajería si todo funcionó bien.

6. Activar la base de datos en tiempo real

2efe6805ef369641.png

Importar mensajes

En su proyecto en Firebase consola seleccione el elemento de base de datos en la barra de navegación izquierda. En el menú de desbordamiento de la base de datos seleccione Importar JSON. Vaya a la initial_messages.json archivo en el directorio friendlychat, seleccionarlo y luego haga clic en el botón Importar. Esto reemplazará cualquier dato que esté actualmente en su base de datos. También puede editar la base de datos directamente, usando el verde + y la x roja para agregar y eliminar elementos.

20ccf4856b715b4c.png

Después de importar su base de datos debería verse así:

f3e0367f1c9cd187.png

Confirmar la dependencia de la base de datos de Firebase

En el bloque de dependencias del Podfile archivo, confirman que Firebase/Database está incluido.

Podfile

pod 'Firebase/Database'

Sincronizar mensajes existentes

Agregue código que sincronice los mensajes recién agregados a la interfaz de usuario de la aplicación.

El código que agregue en esta sección:

  • Inicialice la base de datos de Firebase y agregue un oyente para manejar los cambios realizados en la base de datos.
  • Actualizar el DataSnapshot así se le aparecen nuevos mensajes.

Modifique los métodos "deinit", "configureDatabase" y "tableView: cellForRow indexPath:" de su FCViewController; reemplácelo con el código definido a continuación:

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
  }

Prueba de sincronización de mensajes

  1. Haga clic en el 98205811bbed9d74.png Botón Ejecutar.
  2. Haga clic en la sesión en botón Empezar a ir a la ventana de mensajes.
  3. Agrega nuevos mensajes directamente en la consola de Firebase haciendo clic en el símbolo verde + junto a la entrada "mensajes" y agregando un objeto como el siguiente: f9876ffc8b316b14.png
  4. Confirme que aparecen en la interfaz de usuario de Friendly-Chat.

7. Enviar mensajes

Implementar Enviar mensaje

Envíe valores a la base de datos. Cuando use el método push para agregar datos a Firebase Realtime Database, se agregará un ID automático. Estos ID generados automáticamente son secuenciales, lo que garantiza que los mensajes nuevos se agreguen en el orden correcto.

Modifique el método "sendMessage:" de su FCViewController; reemplácelo con el código definido a continuación:

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

Prueba de envío de mensajes

  1. Haga clic en el 98205811bbed9d74.png Botón Ejecutar.
  2. Haga clic en Iniciar sesión para ir a la ventana de mensajes.
  3. Escriba un mensaje y presione enviar. El nuevo mensaje debería estar visible en la interfaz de usuario de la aplicación y en Firebase console.

8. Almacene y reciba imágenes

Confirmar la dependencia de almacenamiento de Firebase

En el bloque de dependencias del Podfile , confirman Firebase/Storage está incluido.

Podfile

pod 'Firebase/Storage'

Activar Firebase Storage en el panel

Vaya a la consola de Firebase y confirme que Storage esté activado con el dominio "gs: //PROJECTID.appspot.com"

b0438b37a588bcee.png

Si, en cambio, está viendo la ventana de activación, haga clic en "COMENZAR" para activarla con las reglas predeterminadas.

c290bbebff2cafa7.png

Configurar FirebaseStorage

FCViewController.swift

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

Reciba imágenes en mensajes existentes

Agrega código que descargue imágenes de Firebase Storage.

Modifique el método "tableView: cellForRowAt indexPath:" de su FCViewController; reemplácelo con el código definido a continuación:

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. Enviar mensajes de imagen

Implementar almacenar y enviar imágenes

Cargue una imagen del usuario, luego sincronice la URL de almacenamiento de esta imagen con la base de datos para que esta imagen se envíe dentro del mensaje.

Modifique el método "imagePickerController: didFinishPickingMediaWithInfo:" de su FCViewController; reemplácelo con el código definido a continuación:

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

Prueba de envío y recepción de mensajes de imagen

  1. Haga clic en el 98205811bbed9d74.png Botón Ejecutar.
  2. Haga clic en Iniciar sesión para ir a la ventana de mensajes.
  3. Haga clic en el icono "agregar una foto" para elegir una foto. El nuevo mensaje con la foto debería estar visible en la interfaz de usuario de la aplicación y en Firebase console.

10. ¡Felicitaciones!

Has utilizado Firebase para crear fácilmente una aplicación de chat en tiempo real.

Lo que hemos cubierto

  • Base de datos en tiempo real
  • Inicio de sesión federado
  • Almacenamiento

Aprende más