Tutorial UIImagePickerController. Tomar fotos con iOS8 y Swift

UIImagePickerController

UIImagePickerControllerEsta entrada te va a gustar.

Lo sé porque cuándo uno empieza en esto del desarrollo iOS le gustan estas cositas.

En este post te enseñaré como puedes añadir a tus aplicaciones la funcionalidad de tomar fotos con iOS8 y Swift.

Aprenderás a usar la cámara del iPhone o iPad para tomar fotos, ver la foto en pantalla, y guardarla en el carrete.

Un Tutorial que nos va a permitir implementar en nuestras Apps la funcionalidad de tomar fotos con iOS8 y Swift.

Me lo dan «to hecho»: la clase UIMagePickerController

Pues sí, como en la mayoría de las clases de Cocoa que nos permiten hacer alguna virguería, implementar es más fácil que pensar en implementarlo.

La clase UIImagePickerController gestiona interfaces suministradas por el sistema para la toma de fotografías y películas en nuestros dispositivos.

Este controlador de imagen gestiona las interacciones del usuario y proporciona los resultados de esas interacciones a un objeto delegado.

Esto significa que tanto la selección de la foto para el guardado o su visualización en la aplicación, como el descarte de la toma, lo gestiona el controlador de imagen UIImagePickerController a través de su delegado.

Por nuestra parte sólo tenemos que «llamar» a este objeto para que a través del método delegado: picker: didFinishPickingMediaWithInfo info: se pueda gestionar la foto tomada.

Ajustar nuestro controlador de vista (ViewController) a los protocolos necesarios

En primer lugar, nuestro ViewController debe ajustarse a 2 protocolos: UINavigationControllerDelegateUIImagePickerControllerDelegate.

El primero es obvio, para presentar la vista de la toma de foto, así como para volver a nuestro ViewController, necesitamos hacer uso de este controlador de navegación.

Por otra parte, el protocolo UIImagePickerControllerDelegate será el encargado de ofrecer a nuestro ViewController el método picker: didFinishPickingMediaWithInfo info: antes mencionado.

Guardar en carrete

Para guardar nuestra foto en carrete debemos declarar una variable de la clase UIImage, de forma que guardaremos de forma temporal la captura.

Para almacenar en el carrete debemos hacer uso del método UIImageWriteToSavedPhotosAlbum.

Vale, vale, que yo no quiero entender nada, quiero que mi App tome una foto y la guarde en carrete

En tu Storyboard añade una imagen y un botón y conéctalos con tu ViewController.

UIImagePickerController-Tomar-fotos-con-iOS8-y-SwiftEn tu ViewController deberás tener una propiedad de tu imagen, y también un método que tendremos que implementar para presentar la vista de toma de la foto.

Declara una variable de la clase UIImagePickerController.

var miControladorImagen: UIImagePickerController!

A continuación implementa el método que has conectado con tu botón de la siguiente manera:

@IBAction func takePhoto(sender: UIButton) {

    1. miControladorImagen =  UIImagePickerController()

    2. miControladorImagen.delegate = self

    3. miControladorImagen.sourceType = .Camera

    4. presentViewController(miControladorImagen, animated: true, completion: nil)

  }

1. Inicializamos el objeto de la clase UIImagePickerController.

2. Hacemos a nuestro ViewController delegado de nuestro objeto.

3. Mediante la propiedad sourceType, simplemente decimos al controlador, la fuente a utilizar al momento de retirar la imagen o definir el tipo de medio disponible.

En nuestro ejemplo estamos usando Camera, pero podemos seleccionar otro valor de la enumeración UIImagePickerControllerSourceType.

4. Presentamos la vista que hemos seleccionado en nuestro objeto UIImagePickerController.

El método delegado

El método delegado es el encargado de gestionar cuándo el usuario cancela la foto tomada, así como de mostrar la misma en pantalla a través de la imagen que hemos añadido en nuestro storyboard y que hemos conectado, también implementaremos su guardado en el carrete.

Este es el método delegado:

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {

  var guardaImagen: UIImage?

    miControladorImagen.dismissViewControllerAnimated(true, completion: nil)

    imageView.image = info[UIImagePickerControllerOriginalImage] as? UIImage

guardaImagen = info[UIImagePickerControllerOriginalImage] as? UIImage

    UIImageWriteToSavedPhotosAlbum(guardaImagen, nil, nil, nil);

  }

Dónde miControladorImagen es un objeto de la clase UIImagePickerController, y imageView es la imagen que he puesto en mi storyboard y que he conectado con mi código creando una propiedad.

Si te fijas en la primera linea de código declaro una variable, que será la variable que luego guarde en mi carrete a través del método UIImageWriteToSavedPhotosAlbum implementado en la última linea de código.

Previamente a esta variable le había pasado el valor de la captura a través del parámetro del método delegado info.

Hacer una foto, o mostrar una del carrete

Aparece la vista de la cámara porque se lo decimos en la propiedad sourceType, si quisiéramos por ejemplo en vez de hacer una foto escoger una de la librería o carrete cambiaríamos esta linea de nuestro código:

miControladorImagen.sourceType = .Camera

Por esta otra:

miControladorImagen.sourceType = .PhotoLibrary

Y esta también nos valdría:

miControladorImagen.sourceType = .SavedPhotosAlbum

Quizá deberíamos eliminar toda la implementación del guardado, pues en este caso sólo queremos mostrar una imagen de nuestro carrete en pantalla.

No funciona en simulador

Por último y muy importante, este ejemplo no podrás probarlo en el simulador, ya que el simulador no puede hacer uso de la cámara, por lo que al intentar tomar una foto te dará un error y la App hará CRASH!

Lo ideal sería implementar un condicional para que evalúe si el dispositivo el cual está ejecutando tu App tiene cámara instalada, esto es tan sencillo como sobreescribir la implementación de nuestro método takePhoto con este condicional:

if (UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)){

Aquí todo el código includo en nuestro método takePhoto.

} else {

println («No hay cámara»)

}

Observa que hacemos uso de la función isSourceTypeAvailable que nos devuelve un boleeano para indicarnos si el dispositivo tiene cámara o no.

Adjunto el proyecto por si quieres descargarlo y echar un vistazo, o copiar y pegar el código 😉

Y por supuesto, si tienes cualquier duda, déjame un comentario.

DESCARGA AQUÍ EL PROYECTO

About The Author
iOS Developer & Instructor at CFE Apps. Enseño a crear aplicaciones iOS a todo el que quiera aprender.

19 Comments

  • vanesa 12/02/2015 @ 20:22

    Como siempre un verdadero placer. ..muchísimas gracias sergio

    • Sergio Becerril 13/02/2015 @ 14:31

      Hola Vanesa,

      Me alegro que te haya gustado, el objetivo principal de estos «Mega-Post» es enseñaros de una forma clara y directa a realizar cosas que podáis usar en vuestras aplicaciones 😉

      Y gracias a ti por visitar el blog y sobre todo por comentar.

      Un abrazo.
      Sergio Becerril

  • Victor 02/04/2015 @ 20:18

    Hola Sergio, muchas gracias por el tutorial.
    En el caso de querer guardar la imagen de la biblioteca o la realizada con camara dentro de la app como sería? Gracias!

    • Sergio Becerril 07/04/2015 @ 00:24

      Hola Victor,

      Podrías hacerlo con la clase NSFileManager, y guardar estas imágenes en la carpeta Documents, o bien en la librería dentro de la SandBox de tu aplicación; esto que preguntas no tiene nada que ver con el tema principal de la entrada, que es el uso de la cámara.

      Para guardar la foto en el dispositivo, es otra «película», es decir, hay que usar persistencia de datos, y sería motivo para otra entrada, muy interesante por cierto.

      Estas cosas y muchas más se ven en mis Cursos para aprender a crear Apps, tanto con Objective-C como con Swift, puedes ver mis Cursos en CFE APPS Online:

      http://www.online.cfeapps.com

      Gracias por visitar mi Blog y por comentar 😉

      Un saludo.

      Sergio Becerril

      • Victor 08/04/2015 @ 22:29

        Muchas gracias Sergio, le echaré un vistazo 😉 Saludos

  • Alejandro 20/07/2015 @ 21:06

    Gracias por compartir tus conocimientos.. tengo una duda .. como se puede trabajar con estilos (CSS) en swift..
    gracias.. saludos,…

  • Othmar 14/11/2015 @ 02:58

    Hola. He estado buscando una solución para esto en Swift y no la he encontrado. Si ya obtuve la imagen principal, ya sea de la cámara o del carrete, ¿cómo puedo ponerle encima otra imagen (De un grupo que tenga precargadas) y ajustarle el tamaño y forma donde quiera el usuario y guardar la composición como una sola imagen?

    Como si quisiera ponerle lentes obscuros a la cara de alguien o algo así.

    Muchas gracias y saludos.

    • Sergio Becerril 15/11/2015 @ 19:32

      Hola Othman,

      Hay que trabajar con filtros y Core Image.

      Me lo apunto para crear una entrada en el blog explicando como se hace.

      Gracias por visitar mi Blog y por comentar.

      Un abrazo.
      Sergio Becerril

  • angel 22/12/2015 @ 18:28

    Me da este error:
    Downloads/UsarLaCamaraiOS8Swift/UsarLaCamaraiOS8Swift/ViewController.swift:43:40: Value of optional type ‘UIImage?’ not unwrapped; did you mean to use ‘!’ or ‘?’?

    En esta linea:
    UIImageWriteToSavedPhotosAlbum(guardaImagen, nil, nil, nil);

    ¿Alguna idea?

    Gracias

    • Sergio Becerril 26/12/2015 @ 14:48

      Hola Ángel,
      Tiene que ver con los Optionals de Swift, lo resuelves haciendo un «Unwrapping Optional» o desempaquetado forzoso, poniendo un símbolo de exclamación detrás del nombre de tu variable, tal que así:

      UIImageWriteToSavedPhotosAlbum(guardaImagen!, nil, nil, nil);

      Todas estas cosas las puedes ver, y aprender, en mi formación premium:

      http://www.online.cfeapps.com

      Un saludo.
      Sergio Becerril

  • Alex Duran 05/05/2016 @ 20:28

    Hay forma de cambiar el icono de la cámara por uno personalizado?

    • Sergio Becerril 11/05/2016 @ 10:54

      Hola Alex,

      Claro que puedes, lo puedes hacer desde el Storyboard, o bien desde el propio código, algo así:

      custom.tabBarItem = UITabBarItem(title: "Texto que quieras para el tabBar", image: UIImage(named: "Nombre de la imagen cuando la pestaña no está seleccionada"), selectedImage: UIImage(named: "Nombre de la imagen cuando está la pestaña seleccionada"))
      

      Gracias por visitar el Blog.

      Un saludo.
      Sergio Becerril

  • erick 14/05/2016 @ 23:12

    Hola gracias por el aporte muy bueno, igual tengo una duda es que he visto en varias app que a veces
    cuando presentan la pantalla para tomar la foto muestra un marco y solo se captura lo que está dentro del marco, si quisiera hacer algo como eso como le podria hacer.

    De antemano muchas gracias

    • Sergio Becerril 23/06/2016 @ 21:14

      Hola Erick,

      Desgraciadamente no tengo ningún tutoría o articulo que enseñe a realizar lo que quieres hacer, pero lo tomo nota de ello para futuros artículos del blog.

      Gracias por visitar el blog y por comentar.

      Un abrazo.
      Sergio Becerril

  • Ismael Naranjo Sanchez 08/08/2016 @ 05:14

    Muchas gracias por Ejemplo me sirvio de mucho, un Abrazo

    • Sergio Becerril 15/08/2016 @ 18:01

      Hola Ismael,

      me alegro que te sirviera el ejemplo.

      Gracias a ti por visitar el blog y por comentar 😉

      Un abrazo.
      Sergio Becerril

  • Mario Alberto Medina Soní 19/10/2018 @ 22:23

    Hola muy buenas tardes, me sirvió mucho tu tutoría, solo tengo una pregunta, como puedo obtener el nombre de la imagen que capturo o como puedo colocarle el nombre, de antemano muchas gracias

  • Sandra 21/02/2020 @ 17:15

    Muy buen tutorial Sergio,
    Me ha ayudado mucho.
    Saludos y claro he revisado tu blog.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.