Ihre .NET-MAUI-App für iOS bauen, ohne einen Mac zu besitzen
Eine .NET-MAUI-App können Sie in Visual Studio unter Windows schreiben. Der iOS-Build braucht trotzdem einen Mac, denn er braucht Xcode. Die Antwort von Microsoft heißt Pair to Mac und steuert einen Mac per SSH. Diese Seite zeigt einen einfacheren Weg, den wir getestet haben: .NET auf einem Mac installieren und im Terminal mit dotnet bauen.
Warum MAUI für iOS einen Mac braucht
Die Seite von Microsoft zu Pair to Mac sagt es klar. Für iOS-Apps braucht man die Build-Werkzeuge von Apple, und die laufen nur auf einem Mac. Visual Studio unter Windows schickt den Build per SSH an einen Mac. Der Mac kompiliert und signiert die App.
Der alte Umweg ist weg. Microsoft hat Visual Studio für Mac am 31. August 2024 eingestellt. Auf einem Mac nutzen Sie jetzt die dotnet-Kommandozeile oder einen Editor wie VS Code mit dem C# Dev Kit.
Der getestete Weg: dotnet auf dem Mac
Verbinden Sie sich per SSH mit dem Mac und installieren Sie das .NET SDK. Dann fügen Sie den MAUI-Workload hinzu und bauen. Unser Test nutzte das Installationsskript von Microsoft und eine neue App aus dem MAUI-Template. Das ist der Build-Job aus dem Workflow, genau so, wie er am 19. Oktober 2026 auf GitHubs Runner macos-26 durchlief.
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: MauiDemoAuf Ihrem eigenen Mac führen Sie dieselben Befehle per SSH aus. Das Installationsskript legt .NET in Ihren Home-Ordner, also braucht es kein sudo. Setzen Sie diese zwei Variablen in jedem neuen Terminal, oder tragen Sie sie in ~/.zshrc ein:
export DOTNET_ROOT=$HOME/.dotnet export PATH=$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools
Installieren Sie den vollen Workload maui, nicht maui-ios. Unser erster Lauf versuchte es nur mit maui-ios. Das Restore schlug mit NETSDK1147 fehl, weil das Template auch Android anspricht und der Workload android fehlte.
Mit EnableCodeSigning=false testen Sie einen Geräte-Build ohne Zertifikat. Das Ergebnis kann weder auf ein Telefon noch zu Apple. Es beweist nur, dass Ihr Code für ios-arm64 kompiliert.
Was der Lauf ausgegeben hat
Diese Zeilen sind aus dem Job-Log kopiert. Der ganze Job dauerte 3 Minuten 21 Sekunden.
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
Der Simulator-Build dauerte 24 Sekunden. Der Geräte-Build dauerte etwas mehr als 2 Minuten, denn ein Release-Build kompiliert vorab für arm64.
Den Workload passend zum Xcode wählen
Jedes Release von .NET für iOS braucht genau eine Xcode-Version. Die Release Notes auf GitHub, in dotnet/macios, nennen sie. Stand 19. Oktober 2026 sind das die Workload-Sets für .NET 10:
- 10.0.402.1 (iOS 27.1.10018) braucht Xcode 27.1. Es erschien am 19. Oktober 2026, mit .NET SDK 10.0.402.
- 10.0.402 (iOS 27.0.10722) braucht Xcode 27.0.
- 10.0.401 (iOS 26.5.10318) braucht Xcode 26.6. Das ist das Paar, das wir ausgeführt haben.
Wir haben auch absichtlich das falsche Paar ausgeführt. Mit dem Workload-Set 10.0.402.1 und ausgewähltem Xcode 26.6 brach der Build mit diesem Fehler ab:
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.
Für Xcode 27.1, den Standard auf unseren Macs, nennen die Release Notes dieses Paar. Wir konnten es nicht ausführen, denn das Image macos-26 von GitHub hat kein Xcode 27.
bash dotnet-install.sh --version 10.0.402 --install-dir "$HOME/.dotnet" dotnet workload install maui --version 10.0.402.1
Die andere Lösung von Microsoft ist, mehrere Xcodes zu behalten und zwischen ihnen zu wechseln. Prüfen Sie, welches aktiv ist, listen Sie die installierten auf und wählen Sie eins:
xcode-select -p ls -d /Applications/Xcode*.app sudo xcode-select -s /Applications/Xcode.app xcodebuild -version
Auf einem Mac von MacRun ist /Applications/Xcode.app das Xcode 26.6 und /Applications/Xcode-27.1.app das Xcode 27.1, der Standard. Auf einem anderen Mac nehmen Sie genau den App-Namen, den ls ausgibt. Sie können stattdessen auch DEVELOPER_DIR für eine Terminal-Sitzung setzen. Microsoft nennt außerdem eine grundlegende Änderung für Xcode 27. iOS-Apps müssen den UIScene-Lebenszyklus übernehmen, sonst stürzen sie beim Start ab.
Auf dem Mac ausführen, signieren und veröffentlichen
Um die App im Simulator zu starten, nutzt der CLI-Leitfaden von Microsoft das Run-Target. Den Simulator sehen Sie über den Bildschirm des Macs, von Windows aus per VNC.
dotnet build -t:Run -f net10.0-ios
Für den App Store fügen Sie Ihre Signieridentität und Ihr Profil hinzu. Das ist das Beispiel von Microsoft, mit net10.0 statt net8.0. Wir konnten es nicht ausführen, denn unser Test hatte kein Zertifikat.
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"
Die .ipa landet in bin/Release/net10.0-ios/ios-arm64/publish. Microsoft verweist für den Upload auf Transporter. Unser Leitfaden zum Veröffentlichen ohne Mac erklärt API-Schlüssel und TestFlight.
Pair to Mac aus Visual Studio: was die Doku verlangt
Vielleicht bleiben Sie lieber in Visual Studio unter Windows. Pair to Mac braucht dann laut Doku von Microsoft Folgendes:
- Entfernte Anmeldung in den Freigabe-Einstellungen des Macs, mit vollem Festplattenzugriff für entfernte Benutzer.
- Xcode installiert und einmal geöffnet. Pair to Mac kann Xcode nicht installieren.
- Mono installiert, und Rosetta auf einem Mac mit Apple Silicon.
- Ein Mac, den Windows erreichen kann. Wenn er nicht aufgeführt ist, nutzen Sie Add Mac und geben seine Adresse ein.
Visual Studio installiert dann .NET per SSH auf dem Mac. Bei einem Mac von MacRun wäre die Adresse seine Tailscale-Adresse. Pair to Mac über Tailscale haben wir nicht getestet, betrachten Sie das also als ungetestet. Der dotnet-Weg oben ist der, den wir ausgeführt haben.
Wer dafür keinen Mac mieten sollte
- Nur bauen. Der Workflow oben läuft so, wie er ist, auf GitHub. Öffentliche Repositories zahlen für Standard-Runner nichts. Private zahlen laut Abrechnungsseite von GitHub $0.062 pro Minute für macOS. Unser Job mit 3 Minuten 21 Sekunden wird als 4 Minuten abgerechnet, etwa 25 Cent.
- Debuggen auf Ihrem eigenen iPhone. Hot Restart in Visual Studio 2022 bringt Debug-Builds ohne Mac auf ein iPhone am USB. In Visual Studio 2026 wird es nicht unterstützt.
- Tägliche Arbeit an iOS. Wenn Sie den Mac jeden Tag brauchen, kann ein Kauf über ein Jahr günstiger sein.
Wann ein gemieteter Mac passt
Ein CI-Job kann Ihnen die App nicht zeigen. Ein gemieteter Mac gibt Ihnen den Simulator, den Debugger und eine Signierung, die Sie von Hand reparieren können. Ein Tagespass von MacRun ist ein dedizierter M6 Mac mini für $15, eine Woche kostet $59. Xcode 27.1 ist der Standard, und Xcode 26.6 ist auch installiert. .NET ist nicht vorinstalliert. Sie installieren es mit den Befehlen oben. Die Installation des Workloads dauerte in unserem Test 34 Sekunden.
Der Mac wird gelöscht, wenn der Pass endet. Pushen Sie vorher Ihren Code und kopieren Sie Ihre .ipa herunter. Unter Xcode von Windows aus finden Sie die Einrichtung des entfernten Bildschirms.
Häufige Fragen
Kann ich eine .NET-MAUI-App für iOS unter Windows ohne Mac bauen?
+
Keinen vollständigen Build. Laut Doku von Microsoft laufen die iOS-Build-Werkzeuge nur auf einem Mac. Visual Studio schickt den Build über Pair to Mac an einen Mac, oder Sie bauen direkt auf einem Mac mit dotnet.
Welches Xcode braucht .NET 10 MAUI?
+
Das hängt vom Workload-Set ab. Am 19. Oktober 2026 braucht das Workload-Set 10.0.402.1 Xcode 27.1, und 10.0.401 braucht Xcode 26.6. Die Release Notes von dotnet/macios nennen das Xcode für jedes Release.
Warum sagt mein MAUI-Build, er brauche ein anderes Xcode?
+
Ihr Workload und Ihr ausgewähltes Xcode passen nicht zusammen. Wechseln Sie Xcode mit sudo xcode-select -s, oder installieren Sie das passende Workload-Set mit dotnet workload install maui --version.
Gibt es Visual Studio für Mac noch?
+
Nein. Microsoft hat Visual Studio für Mac am 31. August 2024 eingestellt. Auf einem Mac nutzen Sie die dotnet-Kommandozeile oder VS Code mit dem C# Dev Kit.
Funktioniert Pair to Mac mit einem Cloud-Mac?
+
Microsoft verlangt einen Mac, den Windows erreichen kann, mit eingeschalteter entfernter Anmeldung. Pair to Mac über Tailscale haben wir nicht getestet. Der getestete Weg ist das Bauen mit dotnet im Terminal des Macs.
Kann ich eine unsignierte MAUI-App für iOS bauen?
+
Ja. In unserem Test baute dotnet build mit -r ios-arm64 und -p:EnableCodeSigning=false eine Geräte-App ohne Zertifikat. Installieren oder hochladen können Sie sie erst, wenn Sie sie signieren.