Curso de Integración Módulos Nativos iOS/Android para Flutter

Cámara iOS nativa con MethodChannel en Flutter

Curso de Integración Módulos Nativos iOS/Android para Flutter

Contenido del curso

Acceso a sensores y cámara

Cámara iOS nativa con MethodChannel en Flutter

Resumen

Integrar la cámara nativa de iOS en una app Flutter requiere modificar el AppDelegate en Swift y comunicarte con Dart mediante un MethodChannel. Aquí aprenderás cómo configurar ese puente, manejar el UIImagePickerController y devolver la ruta de la imagen capturada al lado Flutter, paso a paso y con código real.

¿Cómo configurar el MethodChannel en el AppDelegate de iOS?

El primer paso es abrir el archivo AppDelegate y dejar el controlador raíz tal como está, pero ajustando el nombre del canal para que coincida con el que usas en Flutter. Sobre ese canal aplicas setMethodCallHandler, que recibe la llamada del método y un result.

Dentro del handler validas que el método invocado sea takePicture. Si coincide, llamas a la función nativa que abrirá la cámara. Si no coincide, devuelves FlutterMethodNotImplemented para que la app no falle.

¿Qué es un MethodChannel en Flutter? Es el puente que permite a tu código Dart invocar funciones nativas en Swift o Kotlin y recibir resultados. Funciona como un canal nombrado donde ambos lados acuerdan los métodos disponibles.

¿Cómo crear la función takePicture en Swift?

Declara una función privada llamada takePicture que reciba un FlutterResult como parámetro. Dentro inicializas un UIImagePickerController, defines su sourceType como .camera y asignas el delegate al propio AppDelegate.

Luego validas que el rootViewController sea la vista actual y, si lo es, presentas el picker con present(imagePicker, animated: true). Así abres la cámara nativa sin salir del flujo de la app.

¿Cómo manejar el delegate del UIImagePickerController?

Para que el AppDelegate reciba los eventos de la cámara, necesitas extender la clase. Usa extension AppDelegate: UIImagePickerControllerDelegate, UINavigationControllerDelegate y dentro implementas el método que se dispara cuando el usuario captura la foto.

Ese método es imagePickerController(_:didFinishPickingMediaWithInfo:). Recibe un diccionario info de tipo [UIImagePickerController.InfoKey: Any] con los datos de la imagen capturada.

  • Accede a la URL de la imagen con la clave .imageURL.
  • Convierte esa URL a un path string con la propiedad .path.
  • Guarda esa ruta en una variable para enviarla a Flutter.

¿Por qué necesito dos delegates en la extension? Porque UIImagePickerController hereda comportamiento de navegación. Sin UINavigationControllerDelegate el compilador rechaza la asignación del delegate.

¿Cómo enviar la ruta de la imagen de regreso a Flutter?

Una vez tienes el path de la imagen, necesitas reabrir el canal de comunicación. Obtén el FlutterViewController desde la ventana actual y crea una instancia de FlutterMethodChannel con el mismo nombre que usaste antes y el binaryMessenger del controller.

Sobre ese canal invocas el método detectPicture pasando el path como argumento. Así Flutter recibe la ruta y puede mostrar o procesar la imagen.

Después de invocar el método debes cerrar el picker con picker.dismiss(animated: true, completion: nil). Si olvidas este paso, la cámara queda abierta sobre tu vista Flutter.

¿Qué conceptos clave debo dominar para esta integración?

La comunicación entre Flutter y código nativo se apoya en varias piezas que conviene tener claras antes de seguir.

  • MethodChannel: canal nombrado que conecta Dart con Swift y Kotlin para invocar métodos nativos.
  • setMethodCallHandler: registra qué función se ejecuta cuando Flutter llama un método por el canal.
  • UIImagePickerController: controlador nativo de iOS que abre cámara o galería.
  • sourceType .camera: configura el picker para usar la cámara en vez de la librería de fotos.
  • didFinishPickingMediaWithInfo: callback que se dispara al terminar la captura y entrega los metadatos.
  • InfoKey.imageURL: clave del diccionario info que apunta a la URL temporal de la imagen.
  • FlutterViewController y binaryMessenger: piezas necesarias para construir el FlutterMethodChannel desde el lado nativo.
  • rootViewController: vista raíz desde la que presentas el picker para que aparezca encima del contenido Flutter.

Con estas piezas conectadas, tu app puede tomar una foto con la cámara nativa de iOS y devolver la ruta a Dart sin depender de plugins externos. ¿Cómo lo vas a probar en tu propia interfaz? Cuéntame en los comentarios qué método llamarás desde Dart para disparar takePicture.