Как собрать приложение .NET MAUI под iOS, если у вас нет Mac
Приложение .NET MAUI можно писать в Visual Studio на Windows. Для сборки под iOS всё равно нужен Mac, потому что нужен Xcode. Microsoft предлагает Pair to Mac, который управляет Mac по SSH. Здесь описан более простой путь, который мы проверили: поставить .NET на Mac и собирать командой dotnet в его терминале.
Почему MAUI нужен Mac для iOS
На странице Microsoft про Pair to Mac об этом сказано прямо. Для сборки iOS-приложений нужны инструменты сборки Apple, а они работают только на Mac. Visual Studio на Windows отправляет сборку на Mac по SSH. Mac компилирует и подписывает приложение.
Старого обходного пути больше нет. Microsoft закрыла Visual Studio for Mac 31 августа 2024 года. Теперь на Mac работают через командную строку dotnet или в редакторе вроде VS Code с C# Dev Kit.
Путь, который мы проверили: dotnet на Mac
Подключитесь к Mac по SSH и поставьте .NET SDK. Потом добавьте workload MAUI и соберите. В нашем тесте был скрипт установки от Microsoft и новое приложение из шаблона MAUI. Это задача сборки из workflow, в точности как она прошла на раннере GitHub macos-26 19 октября 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На своём Mac выполните те же команды по SSH. Скрипт установки кладёт .NET в домашнюю папку, поэтому sudo не нужен. Задавайте эти две переменные в каждом новом терминале или добавьте их в ~/.zshrc:
export DOTNET_ROOT=$HOME/.dotnet export PATH=$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools
Ставьте полный workload maui, а не maui-ios. В первом запуске мы пробовали только maui-ios. Восстановление упало с NETSDK1147, потому что шаблон нацелен и на Android, а workload android не был установлен.
EnableCodeSigning=false позволяет проверить сборку для устройства без сертификата. Результат нельзя поставить на телефон или отправить в Apple. Он только доказывает, что код компилируется под ios-arm64.
Что вывел запуск
Эти строки скопированы из лога задачи. Вся задача заняла 3 минуты 21 секунду.
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
Сборка под симулятор заняла 24 секунды. Сборка для устройства заняла чуть больше 2 минут, потому что релизная сборка заранее компилирует код под arm64.
Подберите workload под Xcode
Каждому выпуску .NET for iOS нужна одна точная версия Xcode. Её называют заметки о выпуске на GitHub, в dotnet/macios. На 19 октября 2026 года наборы workload для .NET 10 такие:
- 10.0.402.1 (iOS 27.1.10018) требует Xcode 27.1. Он вышел 19 октября 2026 года вместе с .NET SDK 10.0.402.
- 10.0.402 (iOS 27.0.10722) требует Xcode 27.0.
- 10.0.401 (iOS 26.5.10318) требует Xcode 26.6. Именно эту пару мы запускали.
Неверную пару мы тоже запустили нарочно. С набором workload 10.0.402.1 и выбранным Xcode 26.6 сборка остановилась с такой ошибкой:
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.
Для Xcode 27.1, который стоит на наших Mac по умолчанию, заметки о выпуске дают такую пару. Мы не смогли её запустить, потому что в образе GitHub macos-26 нет Xcode 27.
bash dotnet-install.sh --version 10.0.402 --install-dir "$HOME/.dotnet" dotnet workload install maui --version 10.0.402.1
Другое решение от Microsoft: держать несколько Xcode и переключаться между ними. Проверьте, какой активен, посмотрите список установленных и выберите один:
xcode-select -p ls -d /Applications/Xcode*.app sudo xcode-select -s /Applications/Xcode.app xcodebuild -version
На Mac от MacRun /Applications/Xcode.app это Xcode 26.6, а /Applications/Xcode-27.1.app это Xcode 27.1, он по умолчанию. На другом Mac используйте точное имя приложения, которое выводит ls. Можно также задать DEVELOPER_DIR для одного сеанса терминала. Microsoft также предупреждает о ломающем изменении в Xcode 27. iOS-приложения должны перейти на жизненный цикл UIScene, иначе они падают при запуске.
Запуск, подпись и публикация на Mac
Чтобы запустить приложение в симуляторе, руководство Microsoft по CLI использует цель Run. Симулятор вы видите на экране Mac, из Windows через VNC.
dotnet build -t:Run -f net10.0-ios
Для App Store добавьте свой сертификат подписи и профиль. Это пример Microsoft, где net8.0 заменён на net10.0. Мы не смогли его запустить, потому что в тесте не было сертификата.
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"
Файл .ipa появляется в bin/Release/net10.0-ios/ios-arm64/publish. Для загрузки Microsoft советует Transporter. Наше руководство по публикации без Mac описывает API-ключи и TestFlight.
Pair to Mac из Visual Studio: что требует документация
Возможно, вы хотите остаться в Visual Studio на Windows. Тогда по документации Microsoft для Pair to Mac нужно следующее:
- Remote Login включён в настройках общего доступа Mac, с полным доступом к диску для удалённых пользователей.
- Xcode установлен и один раз открыт. Pair to Mac не умеет ставить Xcode.
- Установлен Mono, а на Mac с Apple silicon ещё и Rosetta.
- Mac, до которого может достучаться Windows. Если его нет в списке, нажмите Add Mac и введите его адрес.
Потом Visual Studio ставит .NET на Mac по SSH. Для Mac от MacRun адресом будет его адрес в Tailscale. Pair to Mac через Tailscale мы не проверяли, так что считайте это непроверенным. Путь с dotnet выше мы запускали.
Кому не стоит арендовать для этого Mac
- Только сборка. Workflow выше работает на GitHub как есть. Публичные репозитории ничего не платят за стандартные раннеры. Частные платят $0.062 в минуту за macOS, по странице оплаты GitHub. Наша задача на 3 минуты 21 секунду оплачивается как 4 минуты, около 25 центов.
- Отладка на своём iPhone. Hot Restart в Visual Studio 2022 ставит отладочные сборки на iPhone по USB без Mac. В Visual Studio 2026 он не поддерживается.
- Работа с iOS каждый день. Если Mac нужен каждый день, купить свой за год может выйти дешевле.
Когда подходит арендованный Mac
Задача CI не покажет вам приложение. Арендованный Mac даёт симулятор, отладчик и настройку подписи, которую можно поправить руками. Суточный доступ MacRun это выделенный Mac mini на M6 за $15, а неделя стоит $59. Xcode 27.1 стоит по умолчанию, Xcode 26.6 тоже установлен. .NET заранее не установлен. Его вы ставите командами выше. В нашем тесте установка workload заняла 34 секунды.
Когда доступ заканчивается, Mac очищается. До этого отправьте код в репозиторий и скопируйте .ipa к себе. Настройка удалённого экрана описана в руководстве Xcode из Windows.
Частые вопросы
Можно ли собрать iOS-приложение .NET MAUI на Windows без Mac?
+
Полную сборку нельзя. В документации Microsoft сказано, что инструменты сборки iOS работают только на Mac. Visual Studio отправляет сборку на Mac через Pair to Mac, или вы собираете на Mac командой dotnet напрямую.
Какой Xcode нужен .NET 10 MAUI?
+
Это зависит от набора workload. На 19 октября 2026 года набору 10.0.402.1 нужен Xcode 27.1, а 10.0.401 нужен Xcode 26.6. Заметки о выпуске dotnet/macios называют Xcode для каждого выпуска.
Почему сборка MAUI пишет, что нужен другой Xcode?
+
Ваш workload и выбранный Xcode не совпадают. Переключите Xcode через sudo xcode-select -s или поставьте набор workload под свой Xcode командой dotnet workload install maui --version.
Visual Studio for Mac ещё доступна?
+
Нет. Microsoft закрыла Visual Studio for Mac 31 августа 2024 года. На Mac используйте командную строку dotnet или VS Code с C# Dev Kit.
Работает ли Pair to Mac с облачным Mac?
+
Microsoft требует Mac, до которого может достучаться Windows, с включённым Remote Login. Pair to Mac через Tailscale мы не проверяли. Сборку командой dotnet в терминале Mac мы проверили.
Можно ли собрать iOS-приложение MAUI без подписи?
+
Да. В нашем тесте dotnet build с -r ios-arm64 и -p:EnableCodeSigning=false собрал приложение для устройства без сертификата. Поставить или загрузить его нельзя, пока вы его не подпишете.