Руководство

Вашу сборку для iOS отклонили. Исправьте и загрузите снова без Mac

Apple прислала письмо или загрузка не прошла, а Mac у вас нет. Сначала проверьте, нужна ли для исправления новая сборка. Иногда нет. Для случаев, где она нужна, здесь есть исправление и команды, чтобы за один день собрать архив, экспортировать и загрузить его снова.

Нужна ли новая сборка?

Не каждая проблема означает пересборку. Эти исправления делаются в App Store Connect из любого браузера:

  • Скриншоты, описание и другой текст страницы продукта.
  • Ответы об экспортном контроле для сборки со статусом Missing Compliance.
  • Ваши ответы в разделе App Privacy в App Store Connect.

Другим исправлениям нужна новая сборка, а значит, Xcode на Mac. Это старый Xcode или SDK, манифест конфиденциальности, строки в Info.plist и изменения в коде или SDK. Каждой новой загрузке также нужен больший номер сборки.

1. Собрано слишком старым Xcode

С 28 апреля 2026 года Apple принимает только загрузки, собранные в Xcode 26 или новее с SDK для iOS 26. Сборка из Xcode 16 это правило не проходит. Чтобы узнать, чем собран архив, прочитайте два ключа из его приложения:

/usr/libexec/PlistBuddy -c 'Print :DTSDKName' -c 'Print :DTXcode' \
  MyApp.xcarchive/Products/Applications/MyApp.app/Info.plist

На раннере GitHub macos-26 это вывело iphoneos26.5 и 2660, то есть Xcode 26.6. На Mac от MacRun по умолчанию стоит Xcode 27.1, и Xcode 26.6 тоже есть. Оба проходят правило.

Одна оговорка: по словам Apple, приложениям на SDK iOS 27.1 с апреля 2027 года понадобятся скриншоты iPhone Duo. Наше руководство по iPhone Duo показывает, как их сделать.

2. Манифест конфиденциальности и API с обязательной причиной

Для некоторых API нужна указанная причина, например для UserDefaults и меток времени файлов. Причины пишутся в файл PrivacyInfo.xcprivacy. С 1 мая 2024 года App Store Connect не принимает приложения, которые это пропускают. Apple также отклоняет манифесты с неожиданными ключами. В её письме указан путь к каждому плохому файлу.

Вот минимальный манифест для приложения, которое читает свои UserDefaults. CA92.1 это код причины Apple для такого использования:

<?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/>
  <key>NSPrivacyTrackingDomains</key>
  <array/>
  <key>NSPrivacyCollectedDataTypes</key>
  <array/>
  <key>NSPrivacyAccessedAPITypes</key>
  <array>
    <dict>
      <key>NSPrivacyAccessedAPIType</key>
      <string>NSPrivacyAccessedAPICategoryUserDefaults</string>
      <key>NSPrivacyAccessedAPITypeReasons</key>
      <array>
        <string>CA92.1</string>
      </array>
    </dict>
  </array>
</dict>
</plist>

Добавьте его в цель приложения. Потом проверьте, что он корректен. Мы запустили эти команды на хорошем файле и на сломанном:

$ plutil -lint MyApp/PrivacyInfo.xcprivacy
MyApp/PrivacyInfo.xcprivacy: OK
$ plutil -lint bad.xcprivacy
bad.xcprivacy: (Value missing for key inside <dict> at line 1)

После архивации файл должен лежать в корне .app. У нас так и было. Если в письме указан сторонний SDK, обновите этот SDK. Его собственный манифест должен покрывать его собственное использование API.

3. Нет строк описания доступа

Если приложение использует камеру, фото или геопозицию, в Info.plist для этого нужна строка с целью. По словам Apple, без неё доступ не работает, и приложение может упасть. Правило App Review 5.1.1(ii) также требует, чтобы строка ясно описывала, как вы используете данные.

<key>NSCameraUsageDescription</key>
<string>Scan receipts to add them to your expenses.</string>

Проверяйте собранное приложение, а не только исходный файл:

plutil -extract NSCameraUsageDescription raw \
  MyApp.xcarchive/Products/Applications/MyApp.app/Info.plist

4. Экспортный контроль

Сборка без ответа о шифровании показывает Missing Compliance в TestFlight. Пересборка для этого не нужна. Откройте сборку в App Store Connect, нажмите Manage и ответьте на вопросы. Чтобы в следующий раз их пропустить, добавьте этот ключ в Info.plist. Ставьте false, только если ваше шифрование освобождено от контроля, например обычный HTTPS:

<key>ITSAppUsesNonExemptEncryption</key>
<false/>

5. Неверные или отсутствующие скриншоты

Скриншотам пересборка не нужна, но нужен правильный размер. Apple требует хотя бы один скриншот iPhone в размере среднего дисплея с Dynamic Island. Это 1179 x 2556 или 1206 x 2622 пикселя в портретной ориентации. Если iPhone под рукой нет, их делает симулятор:

xcrun simctl boot "iPhone 17 Pro"
xcrun simctl install "iPhone 17 Pro" MyApp.app
xcrun simctl launch "iPhone 17 Pro" com.example.myapp
xcrun simctl io "iPhone 17 Pro" screenshot shot.png
sips -g pixelWidth -g pixelHeight shot.png

Наш скриншот с iPhone 17 Pro вышел размером 1206 x 2622, это нужный размер. iPhone 17 Pro Max дал 1320 x 2868, это подходит для большого набора. Выполните xcrun simctl list devices available, чтобы увидеть, что установлено.

Пересборка и загрузка

Увеличьте номер сборки, потом соберите архив. На нашем тестовом раннере этот шаг занял 12 секунд для маленького приложения на SwiftUI:

xcodebuild archive -project MyApp.xcodeproj -scheme MyApp \
  -destination 'generic/platform=iOS' \
  -archivePath build/MyApp.xcarchive \
  MARKETING_VERSION=1.0.1 CURRENT_PROJECT_VERSION=3

Дальше экспортируйте подписанный .ipa. Запишите это в ExportOptions.plist со своим Team ID. Ключи взяты из xcodebuild -help:

<?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>method</key>
  <string>app-store-connect</string>
  <key>teamID</key>
  <string>ABCDE12345</string>
  <key>signingStyle</key>
  <string>automatic</string>
</dict>
</plist>
xcodebuild -exportArchive -archivePath build/MyApp.xcarchive \
  -exportOptionsPlist ExportOptions.plist -exportPath build/export \
  -allowProvisioningUpdates

Сначала войдите в Xcode со своим Apple Account. У нашего тестового архива без подписи не было команды, и экспорт остановился с ошибкой "error: exportArchive No Team Found in Archive".

На странице Apple про загрузку перечислены Xcode, Transporter и altool. С altool один раз сохраните пароль приложения в связке ключей. Потом проверьте и загрузите:

xcrun altool --store-password-in-keychain-item altool -u you@example.com -p xxxx-xxxx-xxxx-xxxx
xcrun altool --validate-app -f build/export/MyApp.ipa -t ios -u you@example.com -p @keychain:altool
xcrun altool --upload-app -f build/export/MyApp.ipa -t ios -u you@example.com -p @keychain:altool

Или укажите destination со значением upload в ExportOptions.plist. Тогда -exportArchive сам отправит сборку в App Store Connect. Наше руководство по публикации описывает API-ключи и TestFlight.

Исправьте всё за один день

Суточный доступ MacRun стоит $15, оплата один раз, без продления. Это выделенный Mac mini на M6, готовый меньше чем за 5 минут. Установлены Xcode 27.1 и Xcode 26.6, а также симулятор iOS 27.1. Вы подключаетесь через Tailscale по SSH или через VNC-клиент. Если проверка снова вернёт сборку, неделя стоит $59. В конце Mac очищается, поэтому сначала отправьте код в репозиторий.

Кому не стоит арендовать для этого Mac

  • Если исправить нужно скриншоты, текст или ответы об экспорте, используйте App Store Connect в браузере.
  • Приложения на Expo можно пересобрать через EAS Build на машинах Expo с macOS. Смотрите руководство сборка iOS-приложений на Windows.
  • Если вы уже собираете в Codemagic или GitHub Actions, отправьте исправление и дайте CI пересобрать.

Частые вопросы

Можно ли исправить отказ App Store без Mac?

+

Иногда. Скриншоты, текст и ответы об экспортном контроле исправляются в App Store Connect из любого браузера. Новый Xcode, манифест конфиденциальности или изменение Info.plist требуют новой сборки, а для неё нужна macOS.

Какую версию Xcode требует App Store Connect в 2026 году?

+

С 28 апреля 2026 года Apple требует загрузки, собранные в Xcode 26 или новее с SDK для iOS 26. На Mac от MacRun по умолчанию стоит Xcode 27.1, и Xcode 26.6 тоже установлен.

Как добавить манифест конфиденциальности в iOS-приложение?

+

Добавьте в цель приложения файл PrivacyInfo.xcprivacy. Перечислите каждую категорию API с обязательной причиной и код причины Apple, например CA92.1 для собственных UserDefaults приложения. Проверьте файл через plutil -lint и пересоберите.

Моя сборка в TestFlight пишет Missing Compliance. Нужно пересобирать?

+

Нет. Откройте сборку в App Store Connect, нажмите Manage и ответьте на вопросы о шифровании. Чтобы пропустить их, добавьте ITSAppUsesNonExemptEncryption в Info.plist в следующей сборке.

Какой размер скриншотов App Store требует для iPhone?

+

Apple требует хотя бы один скриншот для iPhone с Dynamic Island и средним дисплеем: 1179 x 2556 или 1206 x 2622 пикселя в портретной ориентации. Наш скриншот из симулятора iPhone 17 Pro был 1206 x 2622.

Как загрузить новую сборку без окна Xcode?

+

Экспортируйте .ipa через xcodebuild -exportArchive, потом выполните xcrun altool --upload-app. Transporter тоже подходит. Apple перечисляет оба способа на своей странице про загрузку.

Похожие руководства