1 мая 2024 компания Microsoft официально прекратила поддержку Xamarin.Forms. Альтернативой они называют MAUI, который всё ещё очень и очень сырой. Нельзя так просто взять и перенести свое приложение на новые рельсы - у платформ разные подходы к написанию кода. Так как выкручиваться в таком случае тем, у кого есть legacy проекты на Xamarin.Forms, но при этом нет возможности перевести их на MAUI?

Предисловие

В 2020 году я начал работу над крупным пет-проектом на Xamarin.Forms. Работал по вечерам, после работы. Закончил разработку в 2025 году. Поскольку всё это время я вел разработку через Android-эмулятор, то о проблемах с iOS проектом я даже и не подозревал. Каково было мое удивление, когда я попросту даже не смог скомпилировать iOS приложение на маке...

Проблема 1: невозможно скомпилировать iOS проект

Apple выпускает мажорные обновления Xcode каждый год, а вместе с ним обновляется и инструментарий. Только вот в Xcode 16 они решили "выпилить" часть компонентов, без которых сборка Xamarin-приложения невозможна. Чаще всего это характеризуется ошибкой HE0004: Could not load the framework 'IDEDistribution'

Решений у проблемы 2:

  1. Установить Xcode 15.2 в дополнение к актуальной вашей версии. Это последняя версия, имевшая полную совместимость по пакетам с Xamarin. Далее необходимо выбрать эту версию в системе командой sudo xcode-select -s /Applications/Xcode_15_2.app/Contents/Developer. Также необходимо в настройках JB Rider перейти в настройки -> Build, execution, deployment -> Apple Platforms -> Xcode Path, выбрать там версию 15.2

  2. (Рекомендуется) Можно скопировать недостающие фреймворки внутри Xcode 16+. Для этого в терминале последовательно выполняем команды:

  • cd /Applications/Xcode.app/Contents/SharedFrameworks/IDEDistribution.framework/Versions/A

  • sudo mkdir Frameworks

  • sudo cp -r /Applications/Xcode.app/Contents/SharedFrameworks/AppThinning.framework ./Frameworks

На этом этапе ошибки компиляции должны исчезнуть. Но начинается следующий этап - развертывание на устройстве

Проблема 2: ошибка MT1045 при развертывании приложения на iPhone

После успешной компиляции начинается развертывание приложения на вашем устройстве. Тут вы с большой долей вероятности получите ошибку "Failed to install application on device iPhone Username: error MT1045: Failed to execute 'devicectl': 'devicectl...". Лечится проблема довольно легко:

  1. Открываем Xcode

  2. Создаем там любой Hello World проект

  3. Устанавливаем ему такой же Bundle ID, как и у вашего Xamarin.iOS проекта

  4. Устанавливаем Hello World приложение на свой iPhone

  5. Возвращаемся в JB Rider и устанавливаем свое Xamarin приложение

Проблема 3: PrivacyInfo.xcprivacy вложенных фреймворков

В 2025 году Apple решила дополнительно "позаботиться" о приватности пользователей. Компания внедрила требование по размещению в своем проекте файла PrivacyInfo.xcprivacy с описанием политики сбора персональных данных.

Пример содержимого такого файла:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict> <key>NSPrivacyTracking</key> <false/></dict></plist>

Проблема заключается в том, что все ваши nuget-пакеты, имеющие выход в сеть, должны также отчитаться этим файлом. Как вы понимаете, с этим проблемы... Вы не сможете обновиться до последней версии пакетов, где есть этот файл, так как актуальные версии пакетов не дружат с Xamarin.Forms... Без этого файла вы не сможете загрузить .ipa в AppStore. В случае отправки приложения вы получите ошибку ITMS-91061: Missing privacy manifest.

Как же решить проблему:

  1. Создаем в своем Xamarin.iOS проекте файл PrivacyInfo.xcprivacy, устанавливаем ему свойство "BuildAction" в значение "BundleResource", вставляем в файл значение из примера выше

  2. Открываем Info.plist и устанавливаем там новую версию вашего релиза

  3. Выполняем сборку проекта в JB Rider в конфигурации Release под iPhone (не симулятор!)

  4. Открываем Visual Studio for Mac -> Ваш проект -> View Archives/Прсмотр архивов

  5. Публикуем ipa приложение на рабочий стол

  6. Через Finder находим приложение на рабочем столе и меняем ему расширение с .ipa на .zip

  7. Распаковываем содержимое zip-файла на рабочий стол. Должна распаковаться папка Payload

  8. Заходим в папку Payload и кладем в нее Entitlements.plist из Xamarin.iOS проекта. Если в Entitlements.plist нет информации об идентификаторе приложения, то нужно добавить туда ключ application-identifier со значением <ID команды>.<Bundle ID> . Пример: D2A22DCJF8.ru.keaty.KeatyApp

  9. Правый клик по вашему .app приложению -> "Просмотр содержимого пакета"

  10. Находим там файл PrivacyInfo.xcprivacy и копируем его

  11. Открываем папку Frameworks и вставляем скопированный файл в каждый фреймворк

  12. Вызываем скрипт sign_prod_app.sh (смотри ниже) командой sudo sh sign_prod_app.sh с рабочего стола. Предварительно проверяем, что внутри скрипта указан правильный сертификат и имя приложения

  13. Отправляем приложение в App Store через Transporter App

Исходный код скрипта sign_prod_app.sh:

#!/bin/bash

set -e

CODESIGN_IDENTITY="Apple Distribution: Your Certificate name (Your cert ID)"
APP_PATH="Payload/Your app file name.app"
ENTITLEMENTS_PATH="Payload/Entitlements.plist"
TIME_SUFFIX=$(date +"%H%M%S")
IPA_NAME="App_resigned_$TIME_SUFFIX.ipa"

if [ ! -d "Payload" ]; then
  echo "❌ Ошибка: папка Payload не найдена!"
  exit 1
fi

if [ ! -d "$APP_PATH" ]; then
  echo "❌ Ошибка: .app не найдена!"
  exit 1
fi

if [ ! -f "$ENTITLEMENTS_PATH" ]; then
  echo "❌ Ошибка: Entitlements.plist не найден по пути $ENTITLEMENTS_PATH"
  exit 1
fi

echo "? Подпись фреймворков"
for fw in "$APP_PATH"/Frameworks/*.framework; do
  if [ -d "$fw" ]; then
    echo "? Подписываю фреймворк: $(basename "$fw")"
    codesign -f -s "$CODESIGN_IDENTITY" --timestamp "$fw"
  fi
done

echo "? Подписываю .app с Entitlements"
codesign -f -s "$CODESIGN_IDENTITY" --timestamp --entitlements "$ENTITLEMENTS_PATH" "$APP_PATH"

echo "? Проверка подписи"
codesign --verify --deep --strict --verbose=2 "$APP_PATH"

echo "? Упаковка IPA: $IPA_NAME"
zip -qry "$IPA_NAME" Payload

echo "✅ IPA готова: $IPA_NAME"

Заключение

После проделанных действий ваше приложение должно успешно опубликоваться в AppStore. Неизвестно, сколько еще проживет данный способ, но в июле 2025 у меня успешно получилось опубликовать приложение.

Комментарии (5)


  1. bodyawm
    22.07.2025 00:15

    Благодарю за статью, хоть и преследую обратную цель: есть интерес поднять старую версию Xamarin.iOS времен iPhone 3/4, чтобы иметь возможность быстро писать приложеньки для ретро-айфонов и заодно портировать туда свой движок.

    Пока что стопорюсь на том, что MonoDevelop просит валидный аккаунт Apple с оплаченным аккаунтом разработчика, думаю как бы пропатчить msbuild-скрипт и "вылечить" также, как и XCode (которым я успешно собрал и отлаживал приложение на джейлбрейкнутом 3GS с iOS 6)

    Выдал инвайт


    1. vovaza29 Автор
      22.07.2025 00:15

      Аккаунт разработчика сейчас можно оплатить, привязав оплату МТС к Apple Pay


  1. Fynjy007
    22.07.2025 00:15

    Способ проживёт до мая 2026 года. Предварительно в, примерно апреле, придёт письмо счастья от эппла, что надо использовать свежий sdk и целиться в последние устройства.

    UPD. Это из расчёта, что статья из песочницы свежая, а не пролежала там годик.


    1. bodyawm
      22.07.2025 00:15

      Свежая)


    1. vovaza29 Автор
      22.07.2025 00:15

      Статья свежая) Сам способ я вывел месяца 3 назад. По поводу SDK - сейчас ведь тоже Apple требует использовать его, а свежий сдк совсем не совместим с xamarin.forms. Тем не менее, я обошел ограничения через использование Xcode 15.2 + Свежий Xcode 16+