Guía

Compila una app de React Native para iOS sin Mac

Casi todo el trabajo con React Native funciona bien en Windows o Linux. El build de iOS, no. CocoaPods y xcodebuild necesitan macOS, así que tomas prestado un Mac para ese paso. Abajo tienes un workflow de GitHub Actions que lo hace. Lo ejecutamos el 2 de octubre de 2026 y compiló React Native 0.87.1 con Xcode 26.6.

Qué funciona en Windows y Linux

Tu código JavaScript y TypeScript, Metro y Jest funcionan en cualquier ordenador de escritorio. En nuestra prueba, una app recién creada pasó su test de Jest en el runner ubuntu-24.04 de GitHub y en su runner windows-2025. Los dos usaron Node 22. También puedes compilar y ejecutar la app de Android en cualquiera de los dos sistemas. La documentación de React Native explica la configuración de Android para Windows y para Linux.

Para iOS, esa misma documentación es tajante. En las páginas de configuración para Windows y Linux dice que hace falta un Mac para compilar proyectos con código nativo para iOS. Su propuesta es Expo Go, que ejecuta tu JavaScript en un iPhone real durante el desarrollo. Eso cubre las pantallas y la lógica. No produce una app que puedas publicar.

Qué necesita macOS

  • pod install. El proyecto de iOS descarga React Native y sus dependencias nativas con CocoaPods. Codegen también se ejecuta en este paso.
  • xcodebuild. Xcode y el SDK de iOS solo existen para macOS. Apple pide macOS Tahoe 26.2 o posterior para Xcode 26.6 en su página de requisitos del sistema de Xcode.
  • El simulador. Viene dentro de Xcode, así que también es solo para Mac.
  • Firma y subida. Esa parte se explica en publicar una app de iOS sin Mac.

El workflow que ejecutamos

Crea una app nueva con el comando de reactnative.dev. Ejecuta los tests en Linux y Windows. Después compila iOS en un runner macos-26. Las opciones de init vienen de la documentación de React Native CLI. Eligen npm, se saltan la pregunta de pods y se saltan la configuración de git. Guárdalo en .github/workflows/rn-ios.yml y lánzalo desde la pestaña Actions.

name: rn-ios
on: workflow_dispatch
jobs:
  test-linux:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-node@v7
        with:
          node-version: 22
      - run: npx @react-native-community/cli@latest init RNDemo --pm npm --install-pods false --skip-git-init true
      - run: npm test
        working-directory: RNDemo
  test-windows:
    runs-on: windows-latest
    steps:
      - uses: actions/setup-node@v7
        with:
          node-version: 22
      - run: npx @react-native-community/cli@latest init RNDemo --pm npm --install-pods false --skip-git-init true
      - run: npm test
        working-directory: RNDemo
  build-ios:
    runs-on: macos-26
    steps:
      - uses: actions/setup-node@v7
        with:
          node-version: 22
      - run: sudo xcode-select -s /Applications/Xcode_26.6.app
      - run: xcodebuild -version && node -v && ruby -v
      - run: npx @react-native-community/cli@latest init RNDemo --pm npm --install-pods false --skip-git-init true
      - run: node -p "require('react-native/package.json').version"
        working-directory: RNDemo
      - run: bundle install
        working-directory: RNDemo/ios
      - run: bundle exec pod install
        working-directory: RNDemo/ios
      - name: Build for the iOS Simulator (Debug)
        run: |
          xcodebuild -workspace RNDemo.xcworkspace -scheme RNDemo \
            -configuration Debug -sdk iphonesimulator \
            -destination 'generic/platform=iOS Simulator' \
            -derivedDataPath build build
        working-directory: RNDemo/ios
      - name: Build for the iOS Simulator (Release, JS bundled)
        run: |
          xcodebuild -workspace RNDemo.xcworkspace -scheme RNDemo \
            -configuration Release -sdk iphonesimulator \
            -destination 'generic/platform=iOS Simulator' \
            -derivedDataPath build build
        working-directory: RNDemo/ios
      - run: ls -la build/Build/Products/Release-iphonesimulator/RNDemo.app/main.jsbundle && du -sh build/Build/Products/*-iphonesimulator/RNDemo.app
        working-directory: RNDemo/ios

En tu propio repo, sustituye el paso de init por un checkout de tu código y la instalación de sus paquetes. El resto no cambia. Cambia RNDemo por el nombre de tu workspace y de tu scheme.

Lo que imprimió la ejecución

Estas líneas están copiadas del log del job build-ios. El job de macOS completo tardó 2 minutos y 42 segundos.

Xcode 26.6
Build version 17F113
v22.23.2
0.87.1
Pod install took 43 [s] to run
Pod installation complete! There are 87 dependencies from the Podfile and 86 total pods installed.
** BUILD SUCCEEDED **
Welcome to Metro v0.87.1
** BUILD SUCCEEDED **
-rw-r--r--  1 runner  staff  1268567 Oct  2 04:02 build/Build/Products/Release-iphonesimulator/RNDemo.app/main.jsbundle
154M	build/Build/Products/Debug-iphonesimulator/RNDemo.app
 38M	build/Build/Products/Release-iphonesimulator/RNDemo.app

El build Debug tardó unos 39 segundos y el Release unos 35. Es rápido porque React Native 0.87 descarga un núcleo precompilado. El log de pod install lo decía claramente. Las versiones anteriores compilan mucho más código nativo, así que ahí cuenta con builds más largos.

¿Por qué compilar dos veces? Una app Debug carga su JavaScript desde Metro mientras se ejecuta. El build Release mete el JavaScript dentro de la app como main.jsbundle, aquí de 1,27 MB. Si el build Release pasa, compilan tanto tu bundle como tu código nativo.

Ejecútalo en cada pull request

El workflow de arriba se lanza a mano. Para detectar fallos de iOS antes del merge, cambia la línea del disparador para que también se ejecute en los pull requests:

on:
  pull_request:
  workflow_dispatch:

Cuando un build falla, el log es largo. El nuestro pasó de 18.000 líneas para dos builds pequeños. Busca "error:" en el log y lee la primera coincidencia. Los errores posteriores suelen ser efectos secundarios del primero. Si falla pod install, mira primero el Podfile y tus dependencias nativas.

Cuánto cuesta

GitHub factura cada job redondeando al minuto. Nuestro job de macOS salió a 3 minutos. A $0.062 el minuto, la tarifa de la referencia de precios de runners de GitHub en octubre de 2026, son unos 19 centavos. Los repositorios públicos no pagan nada por los runners estándar. Para unos pocos builds a la semana, es la forma más barata de compilar para iOS.

Con Expo hay otra vía. EAS Build compila iOS en la nube de Expo. El plan Free incluye 15 builds de iOS al mes en una cola de baja prioridad. Después, un build mediano de iOS cuesta $2, según expo.dev/pricing en octubre de 2026.

Dónde el CI se queda corto

Un job de CI demuestra que la app compila. No puede enseñarte la app. Un build para simulador solo se ejecuta en el simulador de iOS, que necesita una pantalla de Mac. Cuando un módulo nativo falla solo en iOS, quieres Xcode abierto. Quieres puntos de interrupción y un simulador en el que puedas hacer clic. Para eso, mira usar Xcode desde Windows con un Mac remoto.

Además, el runner alojado empieza vacío cada vez. Cada ejecución vuelve a descargar los paquetes de Node, las gems y los pods. En nuestra ejecución, el job de macOS también traía un aviso de GitHub. Decía que los jobs de macOS arm64 pueden esperar más en cola por limitaciones de capacidad.

Quién no debería alquilar un Mac para esto

Si compilas unas pocas veces a la semana, quédate con los runners alojados o con EAS. Un Mac dedicado sale a cuenta a partir de unos 2,242 minutos de macOS al mes con la tarifa base de GitHub. También sale a cuenta cuando necesitas la pantalla. Si no se da ninguna de las dos cosas, un Mac alquilado es dinero que no necesitas gastar.

Si pasas de ese límite, el mismo workflow funciona en un runner de macOS self-hosted. Cambia runs-on y apunta xcode-select a tu Xcode. Los pods y los derived data se mantienen entre ejecuciones. Mira los precios de los planes M6.

Preguntas frecuentes

¿Puedo compilar una app de React Native para iOS en Windows?

+

Puedes escribirla y probarla en Windows, pero el build de iOS necesita macOS. La documentación de React Native dice que hace falta un Mac para compilar proyectos con código nativo para iOS. Un Mac en la nube o un runner de CI cubre ese paso.

¿Puedo ejecutar el simulador de iOS en Windows?

+

No. El simulador viene con Xcode, que solo funciona en macOS. Puedes ver el simulador de un Mac remoto con un escritorio remoto, o usar Expo Go en un iPhone real durante el desarrollo.

¿Cuánto tarda un build de React Native para iOS en GitHub Actions?

+

En nuestra ejecución de octubre de 2026, una app nueva de React Native 0.87.1 tardó 2 minutos y 42 segundos en todo el job de macOS. Eso incluye pod install y dos builds para simulador, uno Debug y otro Release. Las apps más grandes tardan más.

¿Necesito una cuenta de Apple Developer para compilar para el simulador?

+

No. Nuestro workflow compiló para el simulador sin ninguna firma. Necesitas el Apple Developer Program de pago para firmar la app para un dispositivo, TestFlight o la App Store.

Guías relacionadas