Guía

Compila tu app de .NET MAUI para iOS sin tener un Mac

Puedes escribir una app de .NET MAUI en Visual Studio en Windows. La build de iOS sigue necesitando un Mac, porque necesita Xcode. La respuesta de Microsoft es Pair to Mac, que controla un Mac por SSH. Esta página muestra un camino más simple que probamos: instalar .NET en un Mac y compilar con dotnet en su terminal.

Por qué MAUI necesita un Mac para iOS

La página de Pair to Mac de Microsoft lo dice claro. Compilar apps de iOS requiere las herramientas de build de Apple, y solo funcionan en un Mac. Visual Studio en Windows envía la build a un Mac por SSH. El Mac compila y firma la app.

La antigua forma de evitarlo ya no existe. Microsoft retiró Visual Studio para Mac el 31 de agosto de 2024. En un Mac ahora usas la línea de comandos de dotnet, o un editor como VS Code con el C# Dev Kit.

El camino que probamos: dotnet en el Mac

Conéctate al Mac por SSH e instala el SDK de .NET. Después añade el workload de MAUI y compila. Nuestra prueba usó el script de instalación de Microsoft y una app nueva de la plantilla de MAUI. Este es el job de build del workflow, tal como pasó en el runner macos-26 de GitHub el 19 de octubre de 2026.

name: maui-ios
on: workflow_dispatch
jobs:
  build-ios-xcode-26-6:
    runs-on: macos-26
    steps:
      - name: Install .NET SDK 10.0.401 into the home folder
        run: |
          curl -sSL https://dot.net/v1/dotnet-install.sh -o dotnet-install.sh
          bash dotnet-install.sh --version 10.0.401 --install-dir "$HOME/.dotnet"
          echo "DOTNET_ROOT=$HOME/.dotnet" >> "$GITHUB_ENV"
          echo "$HOME/.dotnet" >> "$GITHUB_PATH"
      - run: dotnet --version
      - name: Install the MAUI workload (workload set 10.0.401)
        run: time dotnet workload install maui --version 10.0.401
      - run: dotnet workload --info
      - run: sudo xcode-select -s /Applications/Xcode_26.6.app
      - run: xcodebuild -version && sw_vers
      - run: dotnet new maui -n MauiDemo
      - run: grep -n "TargetFrameworks" MauiDemo/MauiDemo.csproj
      - name: Build for the iOS Simulator (Debug)
        run: time dotnet build -f net10.0-ios -c Debug
        working-directory: MauiDemo
      - name: Build for a device, unsigned (Release, ios-arm64)
        run: time dotnet build -f net10.0-ios -c Release -r ios-arm64 -p:EnableCodeSigning=false
        working-directory: MauiDemo
      - name: Publish for a device, unsigned
        continue-on-error: true
        run: time dotnet publish -f net10.0-ios -c Release -r ios-arm64 -p:EnableCodeSigning=false
        working-directory: MauiDemo
      - run: find bin -maxdepth 5 \( -name "*.app" -o -name "*.ipa" \) -print -exec du -sh {} \;
        working-directory: MauiDemo

En tu propio Mac, ejecuta los mismos comandos por SSH. El script de instalación pone .NET en tu carpeta de inicio, así que no necesita sudo. Define estas dos variables en cada terminal nueva, o añádelas a ~/.zshrc:

export DOTNET_ROOT=$HOME/.dotnet
export PATH=$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools

Instala el workload maui completo, no maui-ios. Nuestra primera ejecución probó solo maui-ios. El restore falló con NETSDK1147, porque la plantilla también apunta a Android y faltaba el workload android.

EnableCodeSigning=false te deja probar una build para dispositivo sin certificado. El resultado no puede ir a un teléfono ni a Apple. Solo demuestra que tu código compila para ios-arm64.

Lo que mostró la ejecución

Estas líneas están copiadas del log del job. El job completo tardó 3 minutos y 21 segundos.

Xcode 26.6
Build version 17F113
 Workload version: 10.0.401
Successfully installed workload(s) maui.
  MauiDemo -> .../bin/Debug/net10.0-ios/iossimulator-arm64/MauiDemo.dll
Build succeeded.
Time Elapsed 00:00:23.70
  MauiDemo -> .../bin/Release/net10.0-ios/ios-arm64/MauiDemo.dll
Build succeeded.
Time Elapsed 00:02:06.70
  Created the package: bin/Release/net10.0-ios/ios-arm64/publish//MauiDemo.ipa
 97M	bin/Debug/net10.0-ios/iossimulator-arm64/MauiDemo.app
 16M	bin/Release/net10.0-ios/ios-arm64/publish/MauiDemo.ipa

La build para el simulador tardó 24 segundos. La build para dispositivo tardó algo más de 2 minutos, porque una build Release compila por adelantado para arm64.

Empareja el workload con el Xcode

Cada versión de .NET para iOS necesita una versión exacta de Xcode. Las notas de versión en GitHub, en dotnet/macios, la indican. A 19 de octubre de 2026, estos son los workload sets de .NET 10:

  • 10.0.402.1 (iOS 27.1.10018) necesita Xcode 27.1. Salió el 19 de octubre de 2026, con el SDK de .NET 10.0.402.
  • 10.0.402 (iOS 27.0.10722) necesita Xcode 27.0.
  • 10.0.401 (iOS 26.5.10318) necesita Xcode 26.6. Es la pareja que ejecutamos.

También probamos a propósito la pareja equivocada. Con el workload set 10.0.402.1 y Xcode 26.6 seleccionado, la build se detuvo con este error:

error : This version of .NET for iOS (27.1.10018) requires Xcode 27.1.
The current version of Xcode is 26.6. Either install Xcode 27.1, or use
a different version of .NET for iOS.

Para Xcode 27.1, el predeterminado en nuestros Macs, las notas de versión dan esta pareja. No pudimos ejecutarla, porque la imagen macos-26 de GitHub no tiene Xcode 27.

bash dotnet-install.sh --version 10.0.402 --install-dir "$HOME/.dotnet"
dotnet workload install maui --version 10.0.402.1

La otra solución de Microsoft es tener varios Xcode y cambiar entre ellos. Comprueba cuál está activo, lista los instalados y elige uno:

xcode-select -p
ls -d /Applications/Xcode*.app
sudo xcode-select -s /Applications/Xcode.app
xcodebuild -version

En un Mac de MacRun, /Applications/Xcode.app es Xcode 26.6 y /Applications/Xcode-27.1.app es Xcode 27.1, el predeterminado. En otro Mac, usa el nombre exacto de la app que muestre ls. También puedes definir DEVELOPER_DIR solo para una sesión de terminal. Microsoft también avisa de un cambio importante en Xcode 27. Las apps de iOS deben adoptar el ciclo de vida UIScene, o se cierran al abrirse.

Ejecuta, firma y publica en el Mac

Para abrir la app en el simulador, la guía de CLI de Microsoft usa el target Run. Ves el simulador en la pantalla del Mac, desde Windows por VNC.

dotnet build -t:Run -f net10.0-ios

Para la App Store, añade tu identidad de firma y tu perfil. Este es el ejemplo de Microsoft con net8.0 cambiado a net10.0. No pudimos ejecutarlo, porque nuestra prueba no tenía certificado.

dotnet publish -f net10.0-ios -c Release -p:ArchiveOnBuild=true \
  -p:RuntimeIdentifier=ios-arm64 \
  -p:CodesignKey="Apple Distribution: John Smith (AY2GDE9QM7)" \
  -p:CodesignProvision="MyMauiApp"

El .ipa queda en bin/Release/net10.0-ios/ios-arm64/publish. Microsoft recomienda Transporter para la subida. Nuestra guía para publicar sin Mac explica las claves de API y TestFlight.

Pair to Mac desde Visual Studio: lo que pide la documentación

Quizá prefieras quedarte en Visual Studio en Windows. Entonces Pair to Mac necesita lo siguiente, según la documentación de Microsoft:

  • Remote Login activado en los ajustes de Compartir del Mac, con acceso total al disco para usuarios remotos.
  • Xcode instalado y abierto una vez. Pair to Mac no puede instalar Xcode.
  • Mono instalado, y Rosetta en un Mac con Apple silicon.
  • Un Mac al que Windows pueda llegar. Si no aparece en la lista, usa Add Mac y escribe su dirección.

Después, Visual Studio instala .NET en el Mac por SSH. En un Mac de MacRun, la dirección sería su dirección de Tailscale. No hemos probado Pair to Mac por Tailscale, así que tómalo como no probado. El camino con dotnet de arriba es el que ejecutamos.

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

  • Solo compilar. El workflow de arriba funciona tal cual en GitHub. Los repositorios públicos no pagan nada por los runners estándar. Los privados pagan $0.062 por minuto en macOS, según la página de facturación de GitHub. Nuestro job de 3 minutos y 21 segundos se cobra como 4 minutos, unos 25 centavos.
  • Depurar en tu propio iPhone. Hot Restart en Visual Studio 2022 instala builds Debug en un iPhone conectado por USB sin Mac. No está disponible en Visual Studio 2026.
  • Trabajo diario en iOS. Si necesitas el Mac todos los días, comprar uno puede salir más barato en un año.

Cuándo encaja un Mac alquilado

Un job de CI no te deja ver la app. Un Mac alquilado te da el simulador, el depurador y una configuración de firma que puedes arreglar a mano. Un pase de un día de MacRun es un Mac mini M6 dedicado por $15, y una semana cuesta $59. Xcode 27.1 es el predeterminado y Xcode 26.6 también está instalado. .NET no viene preinstalado. Lo instalas con los comandos de arriba. La instalación del workload tardó 34 segundos en nuestra prueba.

El Mac se borra cuando termina el pase. Sube tu código y copia tu .ipa antes. Consulta Xcode desde Windows para configurar la pantalla remota.

Preguntas frecuentes

¿Puedo compilar una app de .NET MAUI para iOS en Windows sin Mac?

+

No una build completa. La documentación de Microsoft dice que las herramientas de build de iOS solo funcionan en un Mac. Visual Studio envía la build a un Mac con Pair to Mac, o compilas directamente en un Mac con dotnet.

¿Qué Xcode necesita .NET 10 MAUI?

+

Depende del workload set. El 19 de octubre de 2026, el workload set 10.0.402.1 necesita Xcode 27.1, y 10.0.401 necesita Xcode 26.6. Las notas de versión de dotnet/macios indican el Xcode de cada versión.

¿Por qué mi build de MAUI dice que necesita otro Xcode?

+

Tu workload y el Xcode seleccionado no coinciden. Cambia de Xcode con sudo xcode-select -s, o instala el workload set que corresponde a tu Xcode con dotnet workload install maui --version.

¿Sigue disponible Visual Studio para Mac?

+

No. Microsoft retiró Visual Studio para Mac el 31 de agosto de 2024. En un Mac, usa la línea de comandos de dotnet o VS Code con el C# Dev Kit.

¿Funciona Pair to Mac con un Mac en la nube?

+

Microsoft pide un Mac al que Windows pueda llegar, con Remote Login activado. No hemos probado Pair to Mac por Tailscale. Compilar con dotnet en la terminal del Mac es el camino que probamos.

¿Puedo compilar una app de MAUI para iOS sin firma?

+

Sí. En nuestra prueba, dotnet build con -r ios-arm64 y -p:EnableCodeSigning=false generó una app para dispositivo sin certificado. No se puede instalar ni subir hasta que la firmes.

Guías relacionadas