Firebase iOS Codelab Swift

1. Información general

2efe6805ef369641.png

Bienvenido al codelab de Friendly Chat. En este codelab, aprenderá cómo usar la plataforma Firebase para crear aplicaciones de iOS. Implementarás un cliente de chat y monitorearás su rendimiento usando Firebase.

lo que aprenderás

  • Permitir que los usuarios inicien sesión.
  • Sincronice datos utilizando Firebase Realtime Database.
  • Almacene archivos binarios en Firebase Storage.

Lo que necesitarás

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

¿Cómo utilizarás este tutorial?

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

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

Principiante Intermedio Competente

2. Obtenga el código de muestra

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

$ 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 directorio ios-starter/swift-starter desde la descarga del código de muestra
  2. Ejecute 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ías 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 completes el siguiente paso.

4. Crear proyecto de consola Firebase

Crear proyecto

Desde la consola de Firebase , seleccione Agregar proyecto .

Llame al proyecto FriendlyChat , luego haga clic en Crear proyecto .

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

Conecte su aplicación iOS

  1. En la pantalla Descripción general del proyecto de tu nuevo proyecto, haz clic en Agregar Firebase a tu aplicación de iOS .
  2. Ingrese el ID del paquete, como " com.google.firebase.codelab.FriendlyChatSwift ".
  3. Ingrese la identificación de la App Store como " 123456 ".
  4. Haga clic en Registrar aplicación .

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

En la segunda pantalla, haga clic en Descargar GoogleService-Info.plist para descargar un archivo de configuración que contiene todos los metadatos de Firebase necesarios para su aplicación. Copie ese archivo a su aplicación y agréguelo al destino 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 Firebase

Comience asegurándose de que el módulo Firebase esté importado.

AppDelegate.swift , FCViewController.swift

import Firebase

Configurar Firebase en AppDelegate

Utilice el método "configure" en FirebaseApp dentro de la función application:didFinishLaunchingWithOptions para configurar los servicios subyacentes de Firebase 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 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 la sección Base de datos de Firebase console , seleccione Base de datos en tiempo real y luego haga clic en la pestaña 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 esto (incluida la documentación sobre la variable "auth"), consulte la documentación de seguridad de Firebase.

Configurar API de autenticación

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

  1. Navegue a la consola Firebase y seleccione su proyecto
  2. Seleccionar autenticación
  3. Seleccione la pestaña Método de inicio de sesión
  4. Mueva el interruptor de Google a habilitado (azul)
  5. Presione Guardar en el cuadro de diálogo resultante.

Si recibes errores más adelante en este codelab con el mensaje "CONFIGURATION_NOT_FOUND", vuelve a este paso y vuelve a verificar tu trabajo.

Confirmar la dependencia de Firebase Auth

Confirme que existen dependencias de Firebase Auth en el archivo Podfile .

archivo de pods

pod 'Firebase/Auth'

Configure su Info.plist para iniciar sesión en 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 demás campos en blanco.
  3. Cuando esté completa, su configuración debería verse similar a la siguiente (pero con los valores específicos de su aplicación):

1b54d5bd2f4f1448.png

Establecer ID de cliente para iniciar sesión en 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 haya sido 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 como 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

Agregar el método de cerrar 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)")
    }
  }

Pruebe la lectura de mensajes como usuario registrado

  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 mensajes si todo funcionó bien.

6. Activar la base de datos en tiempo real

2efe6805ef369641.png

Importar mensajes

En su proyecto en Firebase console, seleccione el elemento Base de datos en la barra de navegación izquierda. En el menú adicional de la base de datos, seleccione Importar JSON . Busque el archivo initial_messages.json en el directorio amigable de chat, selecciónelo y luego haga clic en el botón Importar . Esto reemplazará cualquier dato que se encuentre 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 archivo Podfile , confirme que Firebase/Database esté incluido.

archivo de pods

pod 'Firebase/Database'

Sincronizar mensajes existentes

Agregue código que sincronice los mensajes recién agregados con 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.
  • Actualice el DataSnapshot para que se muestren los 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
  }

Sincronización de mensajes de prueba

  1. Haga clic en el 98205811bbed9d74.png Botón ejecutar .
  2. Haga clic en el botón Iniciar sesión para comenzar para ir a la ventana de mensajes.
  3. Agregue nuevos mensajes directamente en Firebase console haciendo clic en el símbolo + verde al lado de 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

Enviar valores a la base de datos. Cuando utiliza el método push para agregar datos a Firebase Realtime Database, se agregará una identificación automática. Estas identificaciones generadas automáticamente son secuenciales, lo que garantiza que se agregarán nuevos mensajes 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. Escribe un mensaje y presiona enviar. El nuevo mensaje debería estar visible en la interfaz de usuario de la aplicación y en Firebase console.

8. Almacenar y recibir imágenes

Confirmar la dependencia del almacenamiento de Firebase

En el bloque de dependencias del Podfile , confirme Firebase/Storage esté incluido.

archivo de pods

pod 'Firebase/Storage'

Activar Firebase Storage en el panel

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

b0438b37a588bcee.png

Si en su lugar ve 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()
  }

Recibir imágenes en mensajes existentes

Agregue 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 con imágenes

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 con imágenes

  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!

Ha 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