Spanish (Español) translation by Rafael Chavarría (you can also view the original English article)
Introducción
Más allá de habilitar que los desarrolladores iOS almacenen datos fácilmente en la nube, así como autenticar usuarios a través de sus robustos SDKs, Firebase también proporciona una conveniente solución de almacenamiento para medios. Almacenamiento Firebase permite a los desarrolladores almacenar y recuperar archivos de audio, imagen y video en la nube. Eso es, Almacenamiento Firebase expone un conjunto de SDKs para dar a los desarrolladores la habilidad de administrar sus recursos de contenido generado por los usuarios junto con su producto pariente, la Base de Datos en Tiempo Real Firebase, la cuál almacena contenido de texto de usuario.
Sin embargo, Almacenamiento Firebase es más que solo un contenedor de almacenamiento para recursos ricos en medios. Este asiste a los desarrolladores ofreciendo sincronización sin conexión para usuarios y sus dispositivos, haciendo cola y reanudando imágenes y videos cuando los usuarios se conectan y desconenctan. Esto funciona de manera similar a cómo la Base de Datos en Tiempo Real Firebase orquesta la sincronización de datos de usuario al back-end.



Este tutorial continua desde nuestro tutorial previo sobre Comenzando Con Autenticación Firebase para iOS, en donde vimos cómo administrar, almacenar y trabajar con usuarios en Firebase.
Objetivos de Este Tutorial
Este tutorial te expondrá a los SDKs de Almacenamiento Firebase, para ayudarte a administrar los recursos de medios de tu aplicación---tales como archivos de imagen, audio y video---almacenándolos de manera remota en la nube, y recuperándolos a través de tu aplicación. En este tutorial, aprenderás cómo:
- configurar tu aplicación para Almacenamiento Firebase
- crear y trabajar con referencias de almacenamiento
- cargar medios a Almacenamiento Firebase
- descargar medios desde Almacenamiento Firebase
Conocimiento Supuesto
Este tutorial asume que has tenido algún acercamiento a Firebase, y un antecedente desarrollando con Swift y Xcode. También es importante que hayas ido a través de nuestro turorial Comienza Con Autenticación Firebase para iOS primero ya que necesitarás autenticar a tus usuarios antes de acceder a muchas de las funcionalidades de Almacenamiento Firebase, incluyendo las rutas de recursos.
¿Qué Es Almacenamiento Firebase?
Como desarrollador, puedes usar la Base de Datos en Tiempo Real Firebase para acceder e interactuar con tu cubeta de Almacenamiento Firebase sin servidor, sin la necesidad de crear y hospedar tus propios servidores. Almacenamiento Firebase hace uso de cacheo local en dispositivo para almacenar recursos cuando está sin conexión y sirve recursos cuando el usuario se vuelve a conectar, con los datos locales sincronizados de manera automática.
Los desarrolladores ya no tienen que lidiar con las complejidades de sincronizar datos y contenidos a través de las librerías de red estándar iOS de Apple, y tener que lidiar con múltiples escenarios que podrían causar interrupciones de transferencia.
De hecho, los productos Firebase reconocen que los usuarios móviles del mundo real encaran el prospecto de situaciones de señal interrumpida o baja. Pudiendo sincronizar datos en el dispositivo para transferencia posterior hace una experiencia de usuario mucho mejor, mientras que ahorra a los desarrolladores mucho trabajo.
La seguridad también es importante con Almacenamiento Firebase, como lo es con el resto de los productos Firebase. Esto significa que los desarrolladores pueden restringir el acceso a elementos de almacenamiento autenticando a los usuarios usando Autenticación Firebase, la cuál está construida encima de un modelo imperativo de seguridad que permite control de acceso a rutas, archivos y metadatos en una base rol por rol.
Finalmente, las aplicaciones hospedadas en Almacenamiento Firebase de benefician de una infraestructura Google que escala mientras la base de usuarios crece. Exploraremos algunos de estos conceptos después en el tutorial, pero para comenzar, veamos cómo configurar tu aplicación para trabajar con Firebase. Después echaremos un vistazo a apuntadores de Referencia de Almacenamiento.
Configura el Proyecto
Si has trabajado antes con Firebase, mucho de esto debería ser familiar para ti. De otro modo, necesitarás crear una cuenta en Firebase, y seguir las instrucciones en la sección Configura el Proyecto del artículo Comienza Con Autenticación Firebase para iOS.
Puedes descargar el código fuente completo para este proyecto ingresando lo siguiente en la terminal:
$ git clone git@github.com:tutsplus/get-started-with-firebase-storage-for-ios.git
Para Almacenamiento, necesitaremos agregar Firebase/Storage
a nuestro Podfile, como se muestra abajo:
pod 'Firebase/Core' pod 'Firebase/Storage'
Guarda y después ingresa lo siguiente en tu terminal para construir los pods:
pod install
Dentro del método AppDelegate application:didFinishLaunchingWithOptions:
, la siguiente línea está presente:
FirebaseApp.configure()
Asegúrate que también hayas configurado tu proyecto vía la Consola Firebase correctamente, como se describe en la sección Configura el Proyecto en la sección del tutorial Comienza Con Autenticación Firebase para iOS.
Una vez que tu ambiente está listo, podemos continuar a echar un vistazo a las referencias de almacenamiento, comenzado con cómo crear un apuntador de referencia.
Creando y Trabajando Con Referencias de Almacenamiento
Usando Almacenamiento Firebase, puedes interactuar con tu propia nube, la cuál representa un sistema de archivos de tus imágenes y videos almacenados. Puedes usar lo que se llama una referencia de almacenamiento a una ruta particular o archivo dentro de una ruta, dentro del sistema de archivos al que después das acceso a tu aplicación, para que puedas interactuar con este transfiriendo datos.
Tener un apuntador a una ruta o archivo dentro de la ruta te permite cargar, descargar, actualizar o borrar esa ruta. Para crear una referencia, simplemente creas una instancia de Storage.storage()
, como sigue:
let store = Storage.storage() let storeRef = store.reference()
Ahora tienes una referencia a la raíz de tu jerarquía de sistema de archivos, y puedes establecer la estructura de tu cubeta como desees, por ejemplo creando una estructura de carpeta.
Para acceder archivos y rutas en tu cubeta, llama al método child()
, como sigue:
let userProfilesRef = storeRef.child("images/profiles") ... let logoRef = storeRef.child("images/logo.png")
Las referencias son una base para la ruta completa Firebase a tu archivo vía tu cubeta, en vez de ingresar toda tu ruta URL de cubeta Firebase. Además del método child()
, también puedes navegar tu jerarquía usando los métodos root()
y parent()
, y puedes encadenar estos métodos, como verás abajo:
let userProfilesRef = logoRef.parent()?.child("profiles")
Como puedes, ver, obtendríamos los mismos resultados para userProfilesRef
como en el bloque anterior de código. Lo grandioso sobre las referencias es que son extremadamente livianas, así que puedes tener tantas referencias dentro de tu instancia de aplicación como desees, sin afectar el desempeño de tu aplicación.
Ahora que entiendes los aspectos fundamentales de trabajar con referencias de Almacenamiento Firebase, continuemos a cargar y descargar archivos desde tu cubeta.
Cargando Medios a Almacenamiento Firebase
La manera más sencilla de cargar un archivo es pasar una representación NSData
de sus contenidos en memoria:
let uploadUserProfileTask = userProfilesRef.child("\(userID).png").putData(data, metadata: nil) { (metadata, error) in guard let metadata = metadata else { print("Error occurred: \(error)") return } print("download url for profile is \(metadata.downloadURL)") }
Puedes administrar tus cargas en progreso controlando cuándo comenzar, pausar, reanudar y cancelar tus cargas. También puedes escuchar eventos subsecuentes que son disparados, que son:
- pausar
- reanudar
- cancelar
Referenciando el uploadUserProfileTask
que usamos antes, puedes controlar tus cargas usando los siguientes métodos:
uploadUserProfileTask.pause() uploadUserProfileTask.resume() uploadUserProfileTask.cancel()
También puedes monitorear una transferencia en progreso simplemente estableciendo un observador a la instancia de objeto de la tarea:
let progressObserver = uploadUserProfileTask.observe(.progress) { snapshot in let percentComplete = 100.0 * Double(snapshot.progress!.completedUnitCount) / Double(snapshot.progress!.totalUnitCount) print(percentComplete) }
Veamos cómo podrías aproximarte a descargar imágenes o videos desde la cubeta de almacenamiento.
Descargando Medios Desde Almacenamiento Firebase
Para poder descargar y presentar tus imágenes, comienzas como lo hiciste con la carga, y declaras un apuntador de referencia a tu ruta designada. Después comienzas la descarga usando la función cierre dataWithMaxSize:completion:
:
logoRef.getData(maxSize: 1 * 1024 * 1024) { data, error in if let error = error { print("Error \(error)") } else { let logoImage = UIImage(data: data!) } }
Si haces uso de FirebaseUI, puedes simplemente hacer que FirebaseUI administre la descarga, cacheo y despliegue de imágenes por tu en una manera aún más simple:
... self.imageView.sd_setImage(with: logoRef, placeholderImage: placeholderImage)
Para información sobre implementar FirebaseUI, refierete a la documentación FirebaseUI.
Administrar descargas trabaja de manera similar a administrar y controlar cargas. Aquí está un ejemplo:
let downloadTask = storageRef.child("images/logo.jpg").write(toFile: localFile) // Pause the download downloadTask.pause() // Resume the download downloadTask.resume() // Cancel the download downloadTask.cancel()
También puedes designar un observador como hicimos para las cargas, para seguir el progreso de la transferencia de descarga en tiempo real:
let progressObserverDownload = downloadTask.observe(.progress) { snapshot in let percentComplete = 100.0 * Double(snapshot.progress!.completedUnitCount) / Double(snapshot.progress!.totalUnitCount) print(percentComplete) }
Armado con un vistazo general de cómo trabajar con referencias y cómo cargar y descargar recursos desde tu cubeta, ahora estás listo para echar un vistazo a cómo implementar Almacenamiento Firebase para nuestro proyecto de prueba: FirebaseDo.
El Proyecto de Prueba FirebaseDo
Deberías haber clonado la aplicación FirebaseDo, así que continua y construye y ejecuta el proyecto. Verás que todo lo que hace es autenticar usuarios, usando ya sea teléfono o correo electrónico:



Nuestra meta es mejorar de manera incremental la funcionalidad de la aplicación, así que una vez que nuestros usuarios se autentican de manera exitosa, podrán subir una foto de perfil. La mayoría de nuestro trabajo estará en el HomeViewController
y su Storyboard Asociado. Abordemos el archivo HomeViewController
primero.
El HomeViewController
Antes de que saltemos a los métodos de este controlador, necesitaremos agregar el protocolo UIImagePickerControllerDelegate
a nuestra clase para que podamos trabajar con sus métodos delegados. También necesitaremos agregar una instancia selectora para que nuestros usuarios puedan elegir una foto desde su librería.
class HomeViewController: UIViewController, FUIAuthDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate { @IBOutlet weak var myImageView: UIImageView! let picker = UIImagePickerController() ... fileprivate(set) var auth:Auth? fileprivate(set) var authUI: FUIAuth? //only set internally but get externally fileprivate(set) var authStateListenerHandle: AuthStateDidChangeListenerHandle?
Agrega lo siguiente hacia el final del método viewDidLoad()
:
self.picker.delegate = self self.refreshProfileImage()
Vamos a implementar el método refreshProfileImage()
, el cuál será llamado para descargar la imagen que hemos mostrado en nuestro ViewController. Vamos a afirmar primero que el usuario está de hecho autenticado, antes de crear una referencia que recuperará la imagen de perfil del usuario de la ruta /images/user_id/profile_photo.jpg dentro de nuestra cubeta. Finalmente, actualizaremos nuestra vista de imagen con la imagen recuperada.
func refreshProfileImage(){ if let user = Auth.auth().currentUser{ let store = Storage.storage() let storeRef = store.reference().child("images/\(user.uid)/profile_photo.jpg") storeRef.getData(maxSize: 1 * 1024 * 1024) { data, error in if let error = error { print("error: \(error.localizedDescription)") } else { let image = UIImage(data: data!) self.myImageView.image = image } } }else{ print("You should be logged in") self.loginAction(sender: self) return } }
Después, creamos un método @IBAction
para el botón de librería de fotos el cuál conectaremos a continuación desde nuestro storyboard.
@IBAction func libraryAction(_ sender: Any) { self.picker.allowsEditing = false self.picker.sourceType = .photoLibrary self.picker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)! self.present(picker, animated: true, completion: { print("handle saving") }) }
Finalmente, agregamos dos métodos delegados para nuestro UIImagePickerController
, para manejar cuando el usuario cancela el UIImagePicker
, así como manejar la imagen seleccionada:
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { dismiss(animated: true, completion: nil) } func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) { self.dismiss(animated: true, completion: nil) let profileImageFromPicker = info[UIImagePickerControllerOriginalImage] as! UIImage let metadata = StorageMetadata() metadata.contentType = "image/jpeg" let imageData: Data = UIImageJPEGRepresentation(profileImageFromPicker, 0.5)! let store = Storage.storage() let user = Auth.auth().currentUser if let user = user{ let storeRef = store.reference().child("images/\(user.uid)/profile_photo.jpg") ASProgressHud.showHUDAddedTo(self.view, animated: true, type: .default) let _ = storeRef.putData(imageData, metadata: metadata) { (metadata, error) in ASProgressHud.hideHUDForView(self.view, animated: true) guard let _ = metadata else { print("error occurred: \(error.debugDescription)") return } self.myImageView.image = profileImageFromPicker } } }
Una vez que el usuario selecciona una imagen, desechamos el selector pero mantenemos una referencia a la imagen seleccionada. Después, creamos una instancia StorageMetadata()
para que podamos decirle a Firebase que vamos a cargar un archivo JPEG.
Como hicimos en el método refreshProfileImage()
, vamos a afirmar que el usuario está autenticado, y después creamos una referencia a la ruta de las imágenes en donde queremos almacenar el perfil de nuestro usuario. Usando el método putData()
, cargamos entonces de manera asíncrona nuestra imagen a la ubicación designada de cubeta, antes de establecer nuestra vista de imagen a la imagen recién seleccionada.
Antes de que podamos construir nuestra aplicación, necesitaremos agregar los controles apropiados a nuestro storyboard.
Storyboard
Dentro de nuestro storyboard principal, agrega una vista de imagen con un contenedor de imagen que representará la imagen de perfil actual del usuario, y después arrastra la vista de imagen asociada con la que hemos declarado como un @IBOutlet
en nuestra clase HomeViewController
. Después, agrega una barra de herramientas con un botón que usarás como un @IBAction
para llamar al método libraryAction()
que creamos antes en el HomeViewController
.
Tu Storyboard debería ahora lucir como lo siguiente:



Ausente de cualquier error, puedes continuar y construir y después ejecutar tu aplicación una vez más, y autenticar ya sea creando un nuevo usuario o usando un conjunto de credenciales de usuario existente.
Después se te presentará el HomeViewController
, en donde seleccionarás el botón + para agregar una imagen desde la librería de fotos de tu dispositivo o simulador. Una vez que has elegido una foto, se cargará a la cubeta Firebase. Puedes confirmar que se cargó de manera exitosa yendo a la pestaña Almacenamiento de tu Consola Firebase, como se muestra abajo:



Si detienes y vuelves a ejecutar la aplicación en Xcode, también deberías ver la imagen que subiste al final reaparecer, después confirmando que hemos cargado y descargado de manera exitosa usando Almacenamiento Firebase.
Conclusión
Este tutorial demostró lo sencillo que es agregar almacenamiento de recursos asíncronos y administración a una aplicación Firebase existente con solo unas cuántas líneas de código. Esto te proporciona una manera conveniente de administrar los recursos de tu aplicación, mientras te deja manejar la sincronización sin conexión de forma elegante y conveniente.
Almacenamiento Firebase es una elección obvia para desarrolladores iOS quienes ya están dentro del ecosistema FIrebase. Este proporciona a los desarrolladores la seguridad de un modelo imperativo de seguridad proporcionado por Autenticación Firebase, así como la capacidad proporcionada por la Base de Datos en Tiempo Real Firebase.
Mientras está aquí, ¡revisa algunos de nuestros otros artículos sobre desarrollo de aplicaciones iOS!
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Update me weekly