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 de 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 usando Firebase Realtime Database.
  • Almacene archivos binarios en Firebase Storage.

Lo que necesitarás

  • código x
  • CocoaPods
  • Un dispositivo de prueba con iOS 8.0+ o simulador

¿Cómo utilizará este tutorial?

Léalo 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. Obtenga el código de muestra

Clone 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 compilar la aplicación de inicio:

  1. En una ventana de terminal, navegue hasta el carpeta_estudio_de_android.png directorio ios-starter/swift-starter de la descarga de su 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í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 momento 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. 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 de 2015-11-06 14:13:39.png

Conecta tu aplicación iOS

  1. Desde la pantalla Resumen del proyecto de su nuevo proyecto, haga clic en Agregar Firebase a su aplicación iOS .
  2. Ingrese el ID del paquete, como " com.google.firebase.codelab.FriendlyChatSwift ".
  3. Ingrese la identificación de la tienda de aplicaciones 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 en su aplicación y agréguelo al objetivo de 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 asegurándose de que el módulo Firebase esté importado.

AppDelegate.swift , FCViewController.swift

import Firebase

Configurar Firebase en AppDelegate

Use 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

Usar 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 la consola Firebase , 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 las 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 de Firebase y seleccione su proyecto
  2. Seleccionar autenticación
  3. Seleccione la pestaña Método de inicio de sesión
  4. Cambie el interruptor de Google a habilitado (azul)
  5. Presione Guardar en el cuadro de diálogo resultante.

Si recibe 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.

Confirmar la dependencia de autenticación de Firebase

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

Podfile

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 invertida. 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 ID de cliente para el inicio de sesión de Google

Después de configurar 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 del usuario. Luego agregue un agente de escucha a Firebase Auth, para permitir que el usuario ingrese a la aplicación, después de iniciar sesión correctamente. Y elimine el agente de escucha 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 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 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 de inicio de sesión de Google.
  3. Luego debería ser enviado a la pantalla de mensajes si todo funcionó bien.

6. Activar base de datos en tiempo real

2efe6805ef369641.png

Importar mensajes

En su proyecto en la consola Firebase , 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 de chat amistoso, selecciónelo y luego haga clic en el botón Importar . Esto reemplazará cualquier dato 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.

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.
  • Actualice la DataSnapshot para que se muestren los mensajes nuevos.

Modifique los métodos "deinit", "configureDatabase" y "tableView:cellForRow indexPath:" de su FCViewController; reemplace 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 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

Enviar valores a la base de datos. Cuando usa el método de inserción para agregar datos a Firebase Realtime Database, se agregará una identificación automática. Estos ID generados automáticamente son secuenciales, lo que garantiza que los nuevos mensajes se agregarán en el orden correcto.

Modifique el método "sendMessage:" de su FCViewController; reemplace 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. Almacenar y recibir imágenes

Confirmar dependencia de almacenamiento de Firebase

En el bloque de dependencias del Podfile , confirme que se incluye Firebase/Storage .

Podfile

pod 'Firebase/Storage'

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

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; reemplace 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; reemplace 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 "añadir 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