Compila y publica una app de Flutter para iOS sin tener Mac
Flutter funciona bien en Windows y Linux, hasta que necesitas iOS. En un PC, Flutter ni siquiera ofrece el comando de build para iOS. Ese paso necesita macOS, en un Mac alquilado o en un runner de CI. Hicimos todo el camino el 19 de octubre de 2026, con Flutter 3.47.7 y Xcode 26.6.
Qué funciona en Windows y Linux
Tu código Dart, los tests de widgets y las builds de Android funcionan en un PC. En nuestra prueba, una app nueva pasó flutter test en los runners Windows Server 2025 y Ubuntu 24.04 de GitHub. El job de Ubuntu también generó un APK de Android en modo debug. El hot reload en un emulador de Android funciona igual.
Después pedimos a las dos máquinas una build de iOS. Flutter oculta los comandos de iOS en cualquier sistema que no sea macOS. Los dos runners mostraron la misma línea:
Could not find a subcommand named "ios" for "flutter build".
Su lista de destinos de build ofrecía apk, appbundle, web y el destino de escritorio del sistema. No había ios ni ipa.
Qué necesita macOS
- flutter build ios y flutter build ipa. La guía de publicación de Flutter dice que Xcode es obligatorio y que debes usar un equipo con macOS.
- Paquetes nativos. Desde Flutter 3.44, los plugins entran con Swift Package Manager. Flutter vuelve a CocoaPods para los plugins que aún no lo admiten. Los dos se ejecutan dentro de la build de Xcode.
- El simulador de iOS. Viene con Xcode, así que solo funciona en un Mac. Consulta el simulador de iOS en Windows para ver las opciones.
- Firma y subida. Los certificados y los perfiles se crean y se usan en el Mac.
Instala Flutter en un Mac alquilado
Un Mac de MacRun viene con Xcode 27.1 y el simulador de iOS 27.1. Xcode 26.6 también está instalado. Flutter no viene preinstalado, así que lo añades tú. Tienes acceso admin y Homebrew. Este comando funcionó en nuestra prueba e instaló Flutter 3.47.7 en menos de un minuto:
brew install --cask flutter flutter --version
La documentación de Flutter usa una descarga. Descomprimes el paquete de macOS en una carpeta como ~/develop y añades esta línea a ~/.zprofile:
export PATH="$HOME/develop/flutter/bin:$PATH"
Después viene la configuración de Xcode de la página de iOS de Flutter. Selecciona Xcode, ejecuta las tareas del primer arranque y muestra la licencia. Luego comprueba la plataforma iOS y los runtimes del simulador:
sudo sh -c 'xcode-select -s /Applications/Xcode-27.1.app/Contents/Developer && xcodebuild -runFirstLaunch' sudo xcodebuild -license xcodebuild -downloadPlatform iOS flutter doctor -v
En un Mac de MacRun, Xcode 27.1 está en /Applications/Xcode-27.1.app y ya está seleccionado. Xcode 26.6 está en /Applications/Xcode.app. En otro Mac, usa la ruta que muestre ls -d /Applications/Xcode*.app. En nuestro runner, flutter doctor dio a Xcode una marca verde y encontró CocoaPods 1.17.0. Avisó de las licencias de Android, que no importan para iOS.
Compila y ejecuta en el simulador
Clona tu repo, ejecuta flutter pub get y compila para el simulador. En nuestra prueba, la app tenía un plugin, shared_preferences. No apareció ninguna carpeta Pods, así que Flutter usó Swift Package Manager.
flutter build ios --simulator xcrun simctl list devices available xcrun simctl boot "iPhone Duo" xcrun simctl install booted build/ios/iphonesimulator/Runner.app xcrun simctl launch booted com.example.demo
Usa un nombre de dispositivo de la lista y tu propio bundle ID. En MacRun, el runtime de iOS 27.1 trae el dispositivo iPhone Duo. Con la pantalla compartida también puedes usar flutter run con un simulador arrancado para tener hot reload. Desde Windows, sigue Xcode desde Windows para ver la pantalla del Mac.
El workflow que ejecutamos en GitHub Actions
Este es el job de macOS de nuestra prueba. Crea una app, añade un plugin y compila para el simulador. Después instala y abre la app, y compila y archiva una versión release sin firma.
name: flutter-guide
on: workflow_dispatch
jobs:
macos:
runs-on: macos-26
steps:
- uses: subosito/flutter-action@v2
with:
channel: stable
cache: true
- run: xcodebuild -version && sw_vers
- run: flutter doctor -v
- run: flutter create demo
- run: flutter pub add shared_preferences
working-directory: demo
- name: Simulator build
run: time flutter build ios --simulator
working-directory: demo
- name: Install and launch in the Simulator
run: |
xcrun simctl list devices available | grep -i iphone | head -5
UDID=$(xcrun simctl list devices available -j | python3 -c "import json,sys; d=json.load(sys.stdin)['devices']; print(next(x['udid'] for k,v in d.items() if 'iOS' in k for x in v if x['name'].startswith('iPhone')))")
echo "UDID=$UDID"
xcrun simctl boot "$UDID"
xcrun simctl bootstatus "$UDID"
xcrun simctl install booted build/ios/iphonesimulator/Runner.app
xcrun simctl launch booted com.example.demo
sleep 10
xcrun simctl io booted screenshot shot.png
ls -la shot.png
working-directory: demo
- name: Release build, no signing
run: time flutter build ios --release --no-codesign
working-directory: demo
- name: Archive, no signing
run: time flutter build ipa --no-codesign
working-directory: demoEl job completo tardó 5 minutos y 39 segundos. Estas líneas salen de su log:
[✓] Xcode - develop for iOS and macOS (Xcode 26.6) [5.9s] ✓ Built build/ios/iphonesimulator/Runner.app com.example.demo: 14546 ✓ Built build/ios/iphoneos/Runner.app (14.6MB) ✓ Built build/ios/archive/Runner.xcarchive (170.4MB) Codesigning disabled with --no-codesign, skipping IPA.
La build para el simulador tardó 48 segundos. La build release tardó 1 minuto y 14 segundos, y el archivo 45 segundos. La última línea importa. Sin firma, Flutter se detiene en el archivo. Un .ipa de verdad necesita tu equipo de Apple.
Publica en TestFlight
Necesitas el Apple Developer Program, que cuesta 99 USD al año. Crea la app en App Store Connect desde cualquier navegador. En el Mac, abre ios/Runner.xcworkspace en Xcode una vez. Elige tu equipo en Signing and Capabilities. Después genera el .ipa:
flutter build ipa --build-name 1.0.0 --build-number 2
Flutter escribe el archivo en build/ios/archive y el .ipa en build/ios/ipa. Súbelo con Transporter, o con esta línea de la documentación de Flutter y una clave de API de App Store Connect:
xcrun altool --upload-app --type ios -f build/ios/ipa/*.ipa \ --apiKey your_api_key --apiIssuer your_issuer_id
No pudimos ejecutar los pasos con firma en CI, porque nuestra prueba no tenía cuenta de Apple. Salen de la guía de publicación de Flutter. Para probar en tu propio iPhone, instala la build desde TestFlight. Un Mac remoto no ve un teléfono conectado a tu PC. Nuestra guía de publicación explica las claves de API y la revisión.
Quién no debería alquilar un Mac para esto
Si solo necesitas un .ipa, puede bastar una build en la nube. La guía de publicación de Flutter tiene una sección sobre Codemagic. Las cuentas personales de Codemagic incluyen 500 minutos gratis de build en macOS al mes. Un runner de macOS de GitHub Actions ejecuta el workflow de arriba y cobra por minuto. Si publicas cada semana durante años, un Mac mini usado puede salir más barato con el tiempo.
Un Mac alquilado encaja cuando necesitas ver la app. Es decir, el simulador, las pantallas de firma de Xcode o un fallo en el depurador. Un pase de un día de MacRun cuesta $15 por un Mac mini M6 dedicado, y una semana cuesta $59. Pagas una sola vez y no se renueva nada. El Mac se borra al final, así que sube tu código y guarda tu .ipa antes.
Preguntas frecuentes
¿Puede Flutter compilar iOS en Windows?
+
No. En Windows y Linux, Flutter no ofrece flutter build ios ni flutter build ipa. La guía de publicación de Flutter dice que debes usar un equipo con macOS. Un Mac alquilado o un runner de CI con macOS cubre ese paso.
¿Puedo ejecutar mi app de Flutter en el simulador de iOS desde Windows?
+
No en el propio Windows, porque el simulador viene con Xcode. Puedes compilar en un Mac remoto y ver su simulador con la pantalla compartida. Instalamos y abrimos una app de Flutter con xcrun simctl en un runner de macOS.
¿Flutter sigue necesitando CocoaPods para iOS?
+
Cada vez menos. Desde Flutter 3.44, Swift Package Manager está activado por defecto para iOS. Flutter vuelve a CocoaPods para los plugins que aún no lo admiten. Flutter dice que el registro de CocoaPods pasará a ser de solo lectura el 2 de diciembre de 2026.
¿Puedo generar un .ipa de Flutter sin firma?
+
Puedes archivar sin firma. En nuestra prueba, flutter build ipa --no-codesign creó un .xcarchive de 170.4 MB y luego dijo que se saltaba el IPA. Un .ipa de verdad para TestFlight necesita tu equipo de Apple Developer.
¿Cuánto tarda una build de Flutter para iOS en un Mac?
+
En el runner macos-26 de GitHub, la build para el simulador de una app nueva con un plugin tardó 48 segundos. Una build release sin firma tardó 1 minuto y 14 segundos. Las apps más grandes tardan más.
¿Flutter viene instalado en un Mac de MacRun?
+
No. Están instalados Xcode 27.1, Xcode 26.6 y el simulador de iOS 27.1. Tienes acceso admin y Homebrew, y brew install --cask flutter tardó menos de un minuto en nuestra prueba.