Xcode 27: PrivacyInfo.xcprivacy не попал в Archive? Диагностика 2026
📋 Содержание
По состоянию на 5 октября 2026 года Apple описывает PrivacyInfo.xcprivacy как манифест с данными о практиках приложения или стороннего SDK, а не как файл, наличие которого само по себе подтверждает корректность деклараций (документация Apple о добавлении манифеста). Если PrivacyInfo.xcprivacy не виден в Archive, сначала проверьте фактическое содержимое .xcarchive, затем — ресурсы target, Swift Package и bundle зависимостей. Если файл найден, отдельно проверьте его формат и сведения. Удалённый Mac может сделать сборку повторяемой, но не заменяет проверку архива.
Эта инструкция для разработчиков iOS, у которых в исходниках есть собственный манифест, но архив не проходит проверку.
Она также пригодится инженерам мобильного CI, проверяющим ресурсы Swift Package и сторонних SDK.
DevOps-инженеры найдут здесь порядок сравнения Archive на локальном и удалённом Mac и записи проверяемых результатов.
Последнее обновление: 5 октября 2026 года. Сведения сверены с актуальными на дату проверки страницами Apple о манифестах конфиденциальности, размещении ресурсов, требованиях к сторонним SDK и Xcode. Версию правил для конкретной отправки перепроверьте непосредственно перед публикацией.
Сначала доказательство в Archive, затем проверка проекта
Наличие файла в навигаторе проекта доказывает только то, что файл есть в рабочем каталоге. Оно не подтверждает, что ресурс включён в нужную цель сборки, попал в архив или находится в bundle, где его ожидает обработчик. Сначала сохраните проблемный .xcarchive, чтобы дальнейшая диагностика не зависела от текущего состояния проекта.
Для первоначального поиска используйте путь к архиву как переменную:
ARCHIVE_PATH="/path/to/<App>.xcarchive"
find "$ARCHIVE_PATH/Products/Applications" \
-name "PrivacyInfo.xcprivacy" -print
Структура каталога может различаться в зависимости от того, что именно архивировано и какие продукты в него включены. Поэтому не ограничивайтесь поиском только у корня архива: проверьте приложение, вложенные framework и другие bundles. Поиск показывает расположение файла, но не подтверждает, что декларации верны или что нужный SDK действительно поставлен вместе с манифестом.
| Что проверяете | Наблюдение | Следующее действие |
|---|---|---|
| Исходный проект | Файл есть в каталоге проекта | Проверьте, включён ли он в ресурсы нужного target |
| Архивированное приложение | Файл есть в .app |
Проверьте формат и содержимое манифеста |
| Вложенная зависимость | Файл есть только внутри отдельного bundle | Сопоставьте расположение с типом продукта и документацией SDK |
| Архив | Совпадений нет | Проверьте конфигурацию Archive, копирование ресурсов и разрешённые зависимости |
Для приложения Apple указывает размещение манифеста в соответствующем bundle приложения; для других типов продуктов расположение нужно определять отдельно. Используйте документацию Apple о размещении содержимого в bundle, а не переносите путь, подходящий для приложения, на framework или иной продукт.
Не редактируйте уже подписанный архив, чтобы «добавить недостающий файл». Изменение содержимого после сборки может нарушить подпись. Исправьте исходный проект или интеграцию зависимости, затем создайте новый Archive и повторите проверки.
Собственный манифест: ресурс target или файл в исходниках
Когда манифест приложения не попал в архив, начните с target, который создаёт конечное приложение. Проверьте, что PrivacyInfo.xcprivacy добавлен именно туда, а не только в группу навигатора, тестовый target или другой продукт проекта. Затем откройте настройки сборки и убедитесь, что ресурс участвует в конфигурации, используемой действием Archive.
Один и тот же проект может иметь разные настройки для Debug, Release и пользовательских конфигураций. Поэтому успешный запуск приложения из Xcode не равен успешной проверке Archive: запуск мог использовать другую схему или другой набор параметров. Запишите имя Scheme и конфигурацию из проблемной сборки, а затем воспроизведите Archive с ними же. Не меняйте одновременно Scheme, состав зависимостей и настройки копирования: иначе будет сложнее определить причину расхождения.
| Проверка приложения | Локальная проверка | Признак ошибки |
|---|---|---|
| Принадлежность target | Откройте настройки включения файла в цель сборки | Файл добавлен не в target конечного приложения |
| Ресурсная фаза | Проверьте этапы копирования ресурсов для конфигурации Archive | Манифест отсутствует среди ресурсов этой сборки |
| Выбранная схема | Сверьте Scheme и конфигурацию с фактическим Archive | Проверяется Debug, а архив собран с другой конфигурацией |
| Итоговый bundle | Ищите файл внутри архивированного .app |
Исходник есть, но в конечном bundle совпадений нет |
Для воспроизводимой проверки сначала создайте архив обычным для команды способом, затем зафиксируйте его путь и результат find. При необходимости изучите параметры сборки проекта:
xcodebuild -showBuildSettings \
-workspace "<Workspace>.xcworkspace" \
-scheme "<Scheme>"
Имена workspace и Scheme здесь — заполнители: подставьте значения своего проекта. Выведите только относящиеся к задаче настройки, сохраните журнал сборки и сравните их с конфигурацией CI. Сам по себе вывод настроек не доказывает наличие файла в архиве — это подтверждает осмотр фактического продукта.
Swift Package: объявленный ресурс против файла в Sources
Если манифест принадлежит Swift Package, присутствия PrivacyInfo.xcprivacy в каталоге Sources недостаточно. Пакет должен объявить ресурсы согласно правилам Swift Package Manager. Сверьте структуру пакета с руководством Apple по подключению ресурсов в Swift Package: проверьте описание target в Package.swift, путь к ресурсу и то, что пакетная цель, содержащая ресурс, действительно участвует в сборке приложения.
Разделите проверку на два уровня. Сначала найдите, был ли ресурс включён в bundle, создаваемый пакетом. Затем осмотрите .xcarchive и проверьте, где оказался пакетный bundle относительно приложения и прочих зависимостей. Так вы отличите проблему объявления ресурса в пакете от ситуации, когда ресурс собран отдельно, но проблема находится в составе или настройках конечного приложения.
| Уровень проверки Swift Package | Что подтвердить | Что означает отрицательный результат |
|---|---|---|
| Манифест пакета | Ресурс объявлен для нужной цели пакета | Файл в каталоге сам по себе не включается автоматически |
| Сборка пакета | Цель, содержащая ресурс, разрешена и собрана | Проверьте выбранный продукт и состояние разрешения зависимостей |
| Bundle пакета | Ресурс присутствует в собранном пакете | Вернитесь к декларации ресурса и пути в пакете |
| Приложение в Archive | Ожидаемый bundle и его содержимое сохранены | Проверьте интеграцию продукта пакета и конфигурацию Archive |
Не копируйте пакетный манифест в корень приложения как обходной путь, пока не выяснили, какой компонент должен описывать соответствующие практики. Манифест приложения и манифест SDK относятся к разным продуктам и ответственности; подмена одного другим может оставить фактическую причину незаявленной.
Сторонний SDK: собственный bundle и ответственность поставщика
Для стороннего SDK задайте три отдельных вопроса: поставщик заявляет, что SDK включает собственный манифест? Есть ли файл внутри распространяемого framework или другого bundle? Сохранил ли Archive эту структуру после интеграции? Проверяйте фактически используемую версию SDK и конечный артефакт, а не только документацию или исходный архив поставки.
Apple публикует текущие требования к сторонним SDK и перечень SDK. Сверьте с этой страницей именно версию и статус зависимости, которую использует проект. Нельзя делать вывод, что одинаковое требование относится к любой библиотеке: применимость зависит от актуальных официальных условий и самого SDK. Если поставщик не включает требуемый или заявленный манифест, передайте ему точное имя версии, способ интеграции и результат проверки bundle.
| Где найден файл | Вероятная зона ответственности | Что приложить к разбору |
|---|---|---|
| В bundle SDK и в Archive | Интеграция сохранила ресурс | Версию SDK, путь внутри bundle и результат проверки содержимого |
| В поставке есть, в Archive нет | Настройка упаковки или интеграция приложения | Артефакт поставки, журнал сборки, конечную структуру Archive |
| Нет ни в поставке, ни в Archive | Уточнение у поставщика SDK | Идентификатор версии и ссылку на применимое требование Apple |
| В Archive есть только манифест приложения | Не подтверждено, что SDK описан своим манифестом | Bundle SDK и официальные сведения о поддержке со стороны поставщика |
Не используйте манифест приложения для декларации поведения кода стороннего SDK вместо его собственного описания. Сопоставьте сведения поставщика с документацией Apple о данных, описываемых в манифесте. Если расхождение касается состава данных или API, это уже не проблема копирования файла: требуется сверка заявлений и поведения интегрированной зависимости.
Путь в bundle: приложение против framework
Ошибка «не найдено» иногда оказывается ошибкой ожиданий: проверяется путь приложения, а манифест относится к другому продукту. Определите, какой продукт должен нести файл, и осмотрите соответствующий bundle в Archive. У приложения, framework и иных продуктов структура может различаться. Сначала зафиксируйте фактическое расположение, затем сопоставьте его с указаниями Apple для данного типа продукта.
При поиске учитывайте сразу четыре разные неисправности: файл лежит не в том bundle; ресурс не скопирован; в Archive попал другой продукт или набор зависимостей; файл присутствует, но содержимое неприемлемо. Не называйте их все «Xcode не добавил манифест»: каждая причина требует отдельного исправления и владельца.
Для проверки вывода можно сохранить список найденных путей:
find "$ARCHIVE_PATH/Products/Applications" \
-name "PrivacyInfo.xcprivacy" -print \
> "/tmp/<archive-manifests>.txt"
Замените заполнители своими путями и не включайте в журнал секреты, подписи или закрытые данные проекта. Если поиск ничего не возвращает, расширьте проверку на другие каталоги внутри архива, не предполагая заранее, что все типы продукта обязаны иметь одинаковую структуру.
Манифест найден, но проверка не проходит
Найденный файл — лишь доказательство присутствия. Теперь проверьте, что он является корректным property list, содержит допустимые ключи и значения, а декларации соответствуют тому, как приложение или SDK использует данные и API. Для первичной проверки формата macOS предоставляет plutil:
plutil -lint \
"$ARCHIVE_PATH/Products/Applications/<App>.app/PrivacyInfo.xcprivacy"
Путь в примере предназначен для проверки манифеста приложения. Для файла внутри другого bundle укажите найденное фактическое расположение. Успешная проверка синтаксиса не подтверждает, что значения одобрены или что декларации соответствуют реальному использованию.
Если ошибка связана с API, попадающими под требование указать причину, сверьте назначение и разрешённые причины с официальным описанием Required Reason API. Если сообщение указывает на некорректную структуру или значение, используйте техническую заметку Apple TN3181 о диагностике недействительного манифеста. Исправление зависит от конкретного сообщения: синтаксическая ошибка, недопустимый ключ и несовпадающая декларация — разные причины.
| Результат проверки | Классификация | Безопасное исправление |
|---|---|---|
| Файл отсутствует | Сборка или упаковка | Исправьте ресурс target, пакет или интеграцию SDK и пересоберите Archive |
Файл есть, plutil сообщает об ошибке |
Формат plist | Исправьте исходный файл, затем выполните проверку повторно |
| Формат корректен, но проверка отклоняет декларации | Содержание манифеста | Сверьте ключи, значения и сведения об API с документами Apple |
| Файл приложения корректен, проблема относится к SDK | Граница ответственности | Проверьте манифест внутри bundle SDK и уточните его у поставщика |
На странице Apple о Xcode 27 можно проверить сведения о текущем инструменте. Само упоминание Xcode 27 не доказывает, что правила размещения или содержимого PrivacyInfo.xcprivacy изменились. Не приписывайте версию среды причиной ошибки, пока фактическая проверка не показала различие в сборке или поведении инструмента.
Локальный Archive против удалённого Mac CI
Если локально файл обнаруживается, а сборка удалённого Mac его теряет, сравнивайте результаты на одном и том же коммите. Зафиксируйте версию Xcode, Scheme, конфигурацию Archive и разрешённые версии зависимостей. Затем сохраните путь к архиву и вывод поиска манифестов. Если проверки выполнены на разных исходных версиях или разных пакетах, сравнение не выявит проблему конфигурации.
На удалённом узле проверьте не только, что команда сборки завершилась успешно, но и что последующий шаг проверки реально анализирует созданный .xcarchive. Логи должны связывать коммит, конфигурацию, используемый набор зависимостей и найденные пути. Не помещайте в них сертификаты, приватные ключи и учётные данные. Для сверки надёжнее передавать контрольные сведения о версиях и результаты осмотра, а не копировать весь рабочий каталог без проверки.
Если команда ещё выбирает между собственным узлом и виртуализованной средой, сначала оцените требования к реальному macOS-продукту, воспроизводимости и доступу к сборочным артефактам. В разборе физического и виртуализованного macOS можно сверить различия вариантов, но независимо от выбранного узла проверку манифеста всё равно нужно выполнять на итоговом Archive.
Сценарий различий удалённого CI
Для каждого сравниваемого Archive сохраните одну запись: идентификатор коммита, выбранный Xcode, Scheme, конфигурацию, версии разрешённых зависимостей, результат поиска файлов и результат проверки формата. Сопоставьте записи по порядку:
- Убедитесь, что обе сборки используют один коммит и одинаковые файлы проекта.
- Сверьте версию Xcode и параметры действия Archive.
- Сравните разрешённые версии Swift Package и способ получения бинарных SDK.
- Проверьте, присутствует ли манифест в исходном checkout на CI-узле.
- Проверьте ресурс в bundle пакета или SDK до анализа конечного приложения, если этот артефакт доступен.
- Выполните поиск в итоговом
.xcarchiveна каждом узле. - Запустите проверку формата и свяжите её вывод с конкретным путём найденного файла.
Если исходники на CI не содержат файл, исследуйте checkout и способ доставки ресурса. Если в checkout он есть, но отсутствует в bundle, вернитесь к настройкам target или объявлению Swift Package. Если ресурс внутри зависимости есть, а после Archive его нет, проверяйте упаковку конечного продукта. Если файл есть, но проверка отклоняет содержимое, проблему нельзя исправить простым повтором той же сборки.
Для этой схемы не требуется считать удалённый Mac причиной или гарантией исправления. Его роль — дать контролируемую среду, где вы можете одинаково выполнить Archive и зафиксировать артефакты. Если сборка стабильна локально, но удалённый узел регулярно получает другой набор зависимостей, сначала устраните различие среды; если Archive одинаков, а декларация неверна, исправляйте сам манифест.
Условия выбора следующего действия
Используйте ветвление по наблюдаемому результату, а не по предположению о версии инструмента:
- Если файл отсутствует в исходниках приложения, восстановите его из контролируемого исходного изменения и проверьте, должен ли он принадлежать приложению.
- Если файл есть в проекте, но не попал в
.app, проверьте target membership и ресурсную конфигурацию Archive; затем соберите с той же Scheme. - Если проблема связана со Swift Package, подтвердите декларацию ресурса в пакете и проследите путь от продукта пакета до конечного архива.
- Если проблема ограничена сторонним SDK, осмотрите bundle SDK и уточните состав поставки у его владельца, сверив применимые требования Apple.
- Если файл найден в неподходящем bundle, сначала установите продукт-владелец и ожидаемое расположение по документации Apple, затем исправьте упаковку.
- Если файл найден и синтаксически корректен, но проверка отклоняет его, анализируйте значения и сведения об API по сообщению проверки; не маскируйте ошибку добавлением дубликата в приложение.
- Если локальный и удалённый Archive различаются, повторите сравнение на одном коммите, с одинаковой Scheme и разрешёнными зависимостями; до этого не объявляйте проблему исправленной.
Для релиза сохраняйте Archive, журналы сборки и отчёт проверки как связанный набор доказательств. Не ограничивайтесь скриншотом навигатора Xcode: он показывает проект, а не состав финального продукта. Если после исправления изменился манифест или ресурс, создайте новый Archive и проверьте именно его. Проверка старого архива не подтверждает содержимое новой сборки, а правка уже подписанного продукта затрудняет установление происхождения результата.
Организация воспроизводимой проверки
В CI добавьте отдельный шаг после Archive, который проверяет наличие файлов и формат каждого ожидаемого манифеста. Условие проверки должно учитывать, что манифесты могут располагаться в разных bundle: не требуйте один и тот же путь от всех продуктов. Для приложения проверяйте ожидаемый bundle приложения; для SDK и framework — фактический bundle зависимости и применимые требования. При отсутствии ожидаемого файла завершайте проверку с конкретным путём и типом продукта, а не с общим сообщением «сборка не прошла».
Храните результат проверки вместе с идентификаторами исходного изменения и зависимостей, но исключите секреты подписи и параметры доступа. Это упрощает разбор ситуации, когда один и тот же проект собирается на нескольких узлах. Для временного или независимого узла с macOS можно оценить доступные варианты аренды MacDate, однако выбор инфраструктуры не снимает обязанность проверять содержимое каждой итоговой сборки.
Если локальная машина и текущий CI не дают стабильного сравнения Archive, отдельный удалённый Mac может помочь закрепить воспроизводимую среду и отделить проблемы проекта от различий узлов. Но при постоянной высокой нагрузке, требованиях к физическим интерфейсам или уже доступном подходящем Mac покупка либо собственная инфраструктура могут быть разумнее временной аренды. Когда же вам нужен отдельный macOS-узел для воспроизведения сборки и проверки результата без покупки оборудования, аренда MacDate позволяет рассматривать эту среду как независимый этап приёмки — при условии, что проверку PrivacyInfo.xcprivacy вы всё равно выполняете на фактическом Archive.