Устранение подписей фреймворков CocoaPods при настройке iOS SDK

opoinstall
2026-11-12
5 min read

Как исправить ошибки подписания фреймворков CocoaPods при интеграции iOS SDK? Выявите затронутую неисполняемую цель пакета ресурсов (resource bundle), которая вызывает ошибку Development Team, а затем примените локальное переопределение post_install в CocoaPods вместо отключения подписания глобально для каждого пакета.

В затронутых конфигурациях CocoaPods/Xcode создаваемые цели пакетов ресурсов могут наследовать параметры подписания, из-за чего Xcode запрашивает команду разработчиков (Development Team). Для устранения этих сбоев сборки требуется настроить пользовательские хуки сборки post_install в Podfile для отключения требований к подписи для неисполняемых подцелей ресурсов или выполнить процедуры ручного встраивания XCFramework.

Термин Определение Связанный объект Роль поискового интента
iOS SDK Скомпилированный фреймворк, обеспечивающий мобильную атрибуцию и диплинкинг на iOS. Цель фреймворка Xcode Информационный / Технический
CocoaPods Менеджер зависимостей на уровне приложений для проектов на Swift и Objective-C. Хук сборки Podfile Технический / Информационный
Манифест конфиденциальности Структурированный манифест с подробным описанием правил конфиденциальности приложения или фреймворка. PrivacyInfo.xcprivacy Технический / Соответствие требованиям

Почему правила подписания кода в Xcode 15 и 16 нарушают сборки CocoaPods для iOS SDK

Цепочки сборки Xcode и подписание пакетов ресурсов

Начиная с Xcode 15 и далее в Xcode 16, изменения в системе сборки Xcode повлияли на то, как параметры подписания кода передаются создаваемым подцелям. В затронутых конфигурациях Xcode и CocoaPods неисполняемые цели пакетов ресурсов, в которых упакованы такие ресурсы, как PrivacyInfo.xcprivacy, каталоги активов или локализованные строки, могут наследовать параметры подписания кода, из-за чего Xcode запрашивает команду разработчиков (Development Team).

Эта проблема представляет собой несоответствие интеграции системы сборки в процессе генерации целей CocoaPods, а не жесткое правило Apple, требующее наличия независимой цифровой подписи для каждого отдельного неисполняемого пакета ресурсов.

Анатомия ошибки компиляции: Signing for Target Requires a Development Team

При интеграции зависимостей с помощью CocoaPods менеджер зависимостей создает отдельный проект Pods.xcodeproj, содержащий изолированные цели для каждого пода и связанных с ним пакетов ресурсов. Во время создания архива или компиляции под симулятор Xcode оценивает цели с именами вроде libOpoInstallSDK-OPPrivacy или Pods-YourApp-resource-bundle.

Компиляция завершается характерной ошибкой сборки:

Signing for "libOpoInstallSDK-OPPrivacy" requires a development team.
Select a development team in the Signing & Capabilities editor.

Поскольку CocoaPods генерирует эти подцели динамически при выполнении команды pod install, ручная установка команды разработчиков через графический интерфейс Xcode носит временный характер. Повторный запуск pod install или сборка на чистом воркере CI/CD перезаписывают файл проекта, из-за чего ошибка сборки возвращается.

Ошибка подписания пакета ресурсов iOS, изолированная от подписания исполняемого фреймворка.

Как подцели CocoaPods наследуют свойства без подписи для манифестов конфиденциальности

Некоторые podspec-файлы CocoaPods упаковывают манифесты конфиденциальности через создаваемые подцели пакетов ресурсов (например, с помощью объявлений resource_bundles), в то время как другие поставляют манифесты внутри поставляемых фреймворков или прямых объявлений ресурсов.

В затронутых конфигурациях CocoaPods созданная подцель пакета ресурсов может не иметь пригодного к использованию значения DEVELOPMENT_TEAM или наследовать параметры подписания, которые заставляют Xcode запрашивать его. В результате, пока цель основного приложения собирается с действующим профилем подготовки (provisioning profile), вложенная подцель пакета ресурсов может вызывать предварительную проверку подписания кода в Xcode. Для решения этой проблемы требуется точечное обходное решение на уровне Podfile или переход на ручное встраивание фреймворков.

Как настроить хуки сборки Podfile для устранения ошибок подписания пакетов фреймворков

Общие сведения о хуке выполнения post_install в CocoaPods

CocoaPods предоставляет хук жизненного цикла на базе Ruby под названием post_install внутри файла Podfile. Этот хук выполняется сразу после того, как CocoaPods завершает генерацию файла проекта Pods.xcodeproj, но до записи его на диск. Перехватывая генерацию проекта на этом этапе, разработчики могут программно перебирать созданные цели, проверять типы их продуктов и изменять параметры конфигурации сборки до того, как Xcode начнет компиляцию.

Автоматизация локальных переопределений параметров сборки для подцелей пакетов ресурсов

Чтобы устранить ошибки подписания пакетов как на локальных компьютерах разработчиков, так и на удаленных сборочных агентах CI/CD, хук post_install может проверять имена целей и типы продуктов. Вместо отключения подписания кода глобально для каждого пакета ресурсов CocoaPods (что может создавать риски безопасности для сторонних зависимостей), разработчикам следует ограничить переопределение конкретно затронутыми целевыми пакетами.

Когда цель соответствует типу продукта пакета ресурсов Apple (com.apple.product-type.bundle) и совпадает с указанными именами целей, скрипт очищает настройку сборки CODE_SIGN_IDENTITY и устанавливает для параметра CODE_SIGNING_ALLOWED значение NO. Для конкретно затронутых целей неисполняемых пакетов ресурсов отключение подписания кода на целевом уровне служит целенаправленным обходным решением системы сборки при условии проверки совместимости с финальным архивированным приложением и рабочим процессом отправки в App Store.

Приведенный ниже скрипт на Ruby демонстрирует, как реализовать это локальное переопределение внутри файла Podfile вашего проекта:

# Podfile - Локальное переопределение параметров сборки для подписания пакетов ресурсов
# Разместите этот хук post_install в нижней части файла Podfile вашего проекта

post_install do |installer|
  # Определите конкретные имена целевых пакетов, требующие освобождения от подписания
  affected_bundle_targets = [
    'libOpoInstallSDK-OPPrivacy'
  ]

  installer.pods_project.targets.each do |target|
    next unless target.respond_to?(:product_type)
    next unless target.product_type == 'com.apple.product-type.bundle'
    next unless affected_bundle_targets.include?(target.name)

    target.build_configurations.each do |config|
      # Очистите идентификатор подписи кода и отключите подписание для указанных пакетов ресурсов
      config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
      config.build_settings['CODE_SIGN_IDENTITY'] = ''
    end
  end
end

Локальный хук post install в CocoaPods изменяет только затронутый пакет ресурсов.

Проверка совместимости CI/CD с архивами Xcode и целями сборки для симулятора

После добавления локального хука сборки в файл Podfile выполните команду pod install, чтобы применить обновленные конфигурации к Pods.xcodeproj. Сборки для симулятора часто имеют менее строгие требования к подписи распространения, чем архивы для устройств, однако инженерным командам следует проверять параметры затронутых целей раздельно при локальных запусках в симуляторе, автоматизированных тестовых прогонах CI/CD и конфигурациях релизных архивов Xcode.

Команды диагностической проверки для верификации подписания кода

Проверка параметров сборки целей и идентификаторов подписания кода

При диагностике периодических сбоев подписания на сборочных серверах разработчики могут напрямую запрашивать конфигурацию сборки Xcode с помощью команд терминала. Это позволяет проверить, успешно ли хук post_install в Podfile очистил требования к подписи кода для затронутых подцелей. Обратите внимание, что параметры сборки также можно проверить напрямую для отдельных целей внутри Pods.xcodeproj в Xcode, чтобы убедиться в актуальности целевых значений.

Выполните следующую команду из корневого каталога проекта:

# Проверка параметров сборки подписания кода для рабочего пространства цели
xcodebuild \
  -workspace YourApp.xcworkspace \
  -scheme YourApp \
  -configuration Release \
  -showBuildSettings | grep -E "(CODE_SIGN|DEVELOPMENT_TEAM)"

Аудит архивных пакетов Xcode и целостности подписи

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

Выполните эти команды диагностики в терминале для распакованного IPA (внутри Payload/YourApp.app) или внутри пути архива Xcode .xcarchive (Products/Applications/YourApp.app):

# Проверка наличия манифеста конфиденциальности внутри распакованного пакета IPA
find Payload/YourApp.app -name "PrivacyInfo.xcprivacy" -print

# Для динамически встраиваемого фреймворка проверьте целостность подписи codesign:
codesign -dv --verbose=4 Payload/YourApp.app/Frameworks/OpoInstallSDK.framework

# Выполните глубокую проверку подписи окончательного пакета скомпилированного приложения
# Примечание: Используйте --deep исключительно для инспекции; не используйте --deep во время выполнения подписания кода
codesign --verify --deep --strict --verbose=2 Payload/YourApp.app

Выполнение этой последовательности проверок устанавливает полный цикл диагностики (воспроизведение → проверка → исправление → верификация), гарантирующий соответствие релизных сборок требованиям валидации App Store Connect.

Проверка архива iOS контролирует размещение манифеста конфиденциальности и подписи встроенных фреймворков.

Как импортировать iOS SDK через менеджер зависимостей CocoaPods

Настройка Podfile целевого проекта с помощью pod ‘libOpoInstallSDK’

Интеграция OpoInstall, платформы мобильной атрибуции и диплинкинга, через CocoaPods представляет собой стандартный подход к управлению зависимостями для приложений iOS. Текущий дистрибутив CocoaPods обрабатывает связывание SDK и упакованные ресурсы в соответствии с его podspec-файлом. Включите директиву use_frameworks!, если это требуется текущей интеграцией CocoaPods или архитектурой проекта SDK.

Чтобы добавить зависимость, откройте корневой файл Podfile и укажите целевую зависимость:

target 'YourAppTarget' do
  use_frameworks!
  
  # Импорт SDK атрибуции iOS от OpoInstall
  pod 'libOpoInstallSDK'
end

Выполнение загрузки зависимостей и проверка целостности рабочего пространства

Запустите команду установки из корневого каталога проекта с помощью терминала:

pod install --repo-update

После успешного завершения CocoaPods создает или обновляет файл .xcworkspace. Разработчики должны закрыть стандартный файл .xcodeproj и открыть файл .xcworkspace в Xcode. Проверьте папку проекта Pods, чтобы убедиться, что libOpoInstallSDK и связанная с ним целёвка пакета OPPrivacy отображаются в списке целей Pods.

Инициализация движка SDK в проектных архитектурах на Swift

После связывания фреймворка инициализируйте SDK в делегате жизненного цикла приложения. Инициализируйте SDK в точке жизненного цикла, задокументированной для конкретного выпуска SDK; текущие общедоступные примеры инициализируют его из метода application(_:didFinishLaunchingWithOptions:) для захвата параметров Universal Link при холодном старте и полезных данных динамической установки. Проверьте имена протоколов делегатов и типов моделей данных (например, OpoinstallData или OpoInstallData) на соответствие точной версии поставляемого SDK OpoInstall.

Разработчики могут ознакомиться с полной документацией по iOS SDK атрибуции для получения подробных определений методов делегатов и сигнатур обратного вызова динамических параметров.

Нижеприведенный фрагмент кода демонстрирует, как реализовать протокол OpoInstallDelegate и инициировать запуск SDK в современных кодовых базах на Swift:

// AppDelegate.swift - Инициализация iOS SDK OpoInstall
// Разместите внутри делегата вашего приложения iOS

import UIKit
import libOpoInstallSDK

@main
class AppDelegate: UIResponder, UIApplicationDelegate, OpoInstallDelegate {

    var window: UIWindow?

    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        
        # Инициализация SDK OpoInstall с прослушивателем делегата
        OpoInstallSDK.initWith(self)
        
        return true
    }

    // Метод обратного вызова: обрабатывает параметры, полученные при запуске приложения по диплинку
    func getWakeUpParams(_ appData: OpoinstallData?) {
        if let customData = appData?.data {
            print("OpoInstall SDK: Custom Launch Parameters = \(customData)")
        }
        if let channelCode = appData?.channelCode {
            print("OpoInstall SDK: Channel ID = \(channelCode)")
        }
    }
}

Рабочий процесс ручного импорта фреймворка для целевых проектов iOS

Когда выбирать ручной импорт вместо CocoaPods в корпоративных средах сборки

Хотя CocoaPods упрощает управление пакетами, некоторые корпоративные среды разработки накладывают строгие ограничения на безопасность или среду сборки. Ручная интеграция фреймворков предпочтительна в следующих случаях:

  • Изоляция репозитория: Системы сборки ограничивают исходящие интернет-соединения, предотвращая загрузку зависимостей через pod install во время компиляции.
  • Скорость сборочного конвейера: Исключение шагов анализа CocoaPods и выполнения скриптов сокращает время компиляции в CI/CD.
  • Прямой контроль над бинарными файлами: Политики соответствия безопасности требуют статического анализа двоичных файлов конкретных артефактов .xcframework до их включения в проект.

Загрузка и встраивание артефактов XCFramework

Чтобы вручную импортировать SDK без менеджеров зависимостей, скачайте последний пакет фреймворка iOS SDK. Распакуйте дистрибутивный архив, чтобы найти скомпилированный каталог OpoInstallSDK.xcframework.

Чтобы определить, является ли срез XCFramework статическим или динамическим перед встраиванием, выполните команду file в терминале:

# Запрос типа среза архитектуры двоичного файла
file OpoInstallSDK.xcframework/ios-arm64/OpoInstallSDK.framework/OpoInstallSDK

Следуйте этим шагам для интеграции бинарного файла в Xcode:

  • Шаг 1: Откройте проект вашего основного приложения в Xcode.
  • Шаг 2: Перетащите каталог OpoInstallSDK.xcframework в навигатор проекта Xcode в группу фреймворков основной цели.
  • Шаг 3: В появившемся диалоговом окне установите флажок Copy items if needed (Копировать элементы при необходимости) и выберите основную цель приложения в разделе Add to targets (Добавить к целям).

Настройка путей поиска библиотек и путей поиска фреймворков в Link Binary With Libraries

Перейдите к конфигурации цели вашего приложения в Xcode:

  • Фазы сборки (Build Phases): Разверните раздел Link Binary With Libraries. Убедитесь, что OpoInstallSDK.xcframework присутствует в списке.
  • Параметры сборки (Build Settings): Найдите пункт Framework Search Paths (FRAMEWORK_SEARCH_PATHS). Убедитесь, что указан путь к каталогу, содержащему добавленный вручную фреймворк.
  • Системные зависимости: Добавляйте только те системные фреймворки Apple, которые задокументированы для конкретной версии интегрируемого SDK (например, AdSupport.framework или WebKit.framework). Не добавляйте неподтвержденные устаревшие фреймворки.

Установка правил встраивания и подписывания (Embed and Sign) для динамических и статических бинарных файлов

Выберите цель приложения и перейдите на вкладку General. Найдите раздел Frameworks, Libraries, and Embedded Content:

Статические и динамические бинарные файлы XCFramework следуют разным путям встраивания и подписания в iOS.

  • Динамические фреймворки: Установите параметр встраивания в значение Embed & Sign. Динамические фреймворки должны находиться в каталоге Frameworks конечного пакета приложения, чтобы динамический компоновщик (dyld) мог загрузить их во время выполнения, а Xcode применил подпись кода вашей команды разработчиков при архивировании.
  • Статические фреймворки без ресурсов: Достаточно связать двоичный файл, а встраивание фреймворка обычно не требуется, так как статический код компилируется непосредственно в исполняемый файл основного приложения.
  • Статические фреймворки с ресурсами (включая манифесты конфиденциальности): Следуйте рекомендациям поставщика SDK по распространению. Для статических фреймворков Xcode 15+, созданных для упаковки встроенных ресурсов, Apple документирует добавление фреймворка с параметром Embed & Sign; Xcode опускает уже статический связанный двоичный файл, сохраняя и подписывая пакет фреймворка и его встроенные ресурсы.

Устранение конфликтов подписи PrivacyInfo.xcprivacy в CocoaPods

Требования Apple к манифесту конфиденциальности для сторонних зависимостей фреймворков

Сторонним SDK может потребоваться включить манифест PrivacyInfo.xcprivacy в зависимости от использования их API, практик сбора данных, поведения отслеживания и того, входит ли SDK в опубликованный Apple список SDK, подпадающих под требования явного манифеста.

Текущий дистрибутив OpoInstall включает манифест PrivacyInfo.xcprivacy; разработчики должны проверить его объявления на соответствие конкретной версии поставляемого SDK и текущим рекомендациям Apple по отправке приложений перед началом архивации.

Устранение конфликтов ресурсов дублирования манифестов конфиденциальности

При создании приложения, объединяющего несколько сторонних зависимостей, Xcode обнаруживает манифесты конфиденциальности в архивированном приложении и связанных пакетах SDK, объединяя их объявления при создании отчета о конфиденциальности Xcode (Xcode Privacy Report) для аудита включенных заявлений о конфиденциальности.

Если проект ошибочно включает дублирующиеся файлы манифеста конфиденциальности непосредственно в этап Copy BundleResources основной цели, Xcode может выдать предупреждение или ошибку сборки:

Multiple commands produce '.../PrivacyInfo.xcprivacy'

Для разрешения этого конфликта:

  • Расположение манифеста фреймворка: Для iOS XCFramework файл PrivacyInfo.xcprivacy должен находиться внутри каждого применимого варианта фреймворка для конкретной платформы (например, OpoInstallSDK.xcframework/ios-arm64/OpoInstallSDK.framework/PrivacyInfo.xcprivacy), а не помещаться в корневой каталог контейнера XCFramework.
  • Ресурсы основного приложения: Сохраняйте объявления конфиденциальности главного приложения в ресурсах основной цели, позволяя вариантам фреймворков SDK управлять своими соответствующими файлами манифеста внутренне.

Проверка объявлений API обязательного назначения (Required Reason API) внутри PrivacyInfo.xcprivacy

Изучите содержимое манифеста конфиденциальности, чтобы убедиться, что все объявленные категории API соответствуют официальным спецификациям API обязательного назначения Apple. Откройте PrivacyInfo.xcprivacy в виде списка свойств (Property List) или чистого XML в Xcode. Объявления должны строго соответствовать необходимым вариантам использования API:

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

Включайте только те категории API и утвержденные коды причин, которые соответствуют фактическим требованиям реализации SDK.

Проверка финальных отправок IPA в App Store Connect

Перед отправкой обновления приложения в App Store Connect проверьте скомпилированный архив IPA локально:

  • Шаг 1: В Xcode выберите пункт меню Product > Archive.
  • Шаг 2: После завершения архивации нажмите кнопку Validate App в окне Organizer.
  • Шаг 3: Xcode проверяет подписи встроенных фреймворков, права подготовки (entitlements) и схемы манифестов конфиденциальности на серверах проверки Apple.

Успешная валидация указывает на то, что архив прошел этот этап проверки перед отправкой; это служит необходимым шагом проверки сборки перед отправкой в TestFlight или продакшн.

Сравнительный анализ CocoaPods и ручного импорта фреймворков для iOS

Компромиссы в обслуживании, изоляции подписей и автоматизации сборки

Выбор между CocoaPods и ручной интеграцией фреймворков предполагает оценку рабочих процессов команды, возможностей сборочных серверов и затрат на поддержку зависимостей. Хотя CocoaPods автоматизирует обновление версий, обновление версий Xcode может потребовать корректировки хуков post_install в Podfile в соответствии с меняющимися правилами подписания Apple.

В таблице ниже приведено подробное техническое сравнение обоих вариантов импорта:

Аспект функции Менеджер зависимостей CocoaPods Ручное встраивание фреймворка (.xcframework)
Управление версиями Автоматизировано через pod update Ручная загрузка и замена бинарных файлов
Настройка параметров сборки Скрипты на базе хуков Ruby в Podfile Настройка напрямую в параметрах цели Xcode
Управление подписью кода Может потребоваться локальное обходное решение через post_install Прямой контроль в параметрах целевого фреймворка
Обработка манифеста конфиденциальности Управляется через ресурсы подов; Xcode объединяет обнаруженные манифесты в отчет о конфиденциальности Проверяется внутри каждого варианта фреймворка
Сложности с конвейером CI/CD Низкие (требуется синхронизация Podfile.lock) Низкие (фреймворк хранится в системе контроля версий)

Оценка стратегий управления зависимостями в корпоративных мобильных командах

CocoaPods остается практичным вариантом для команд, которые уже используют стандартизированное управление зависимостями на основе Podfile благодаря автоматическому разрешению зависимостей и централизованной фиксации версий с помощью Podfile.lock. Внедрение локального скрипта переопределения подписи на Ruby помогает устранить блокировки подписания на уровне целей на рабочих станциях разработчиков и в средах сборки CI/CD.

Часто задаваемые вопросы (FAQ)

Почему Xcode сообщает об ошибках подписания для пакетов ресурсов в CocoaPods?
В некоторых конфигурациях Xcode 15/16 и CocoaPods создаваемые неисполняемые цели пакетов ресурсов могут наследовать параметры подписания, из-за чего Xcode запрашивает команду разработчиков (Development Team). Если эти подцели наследуют неполные свойства подписания кода в созданных конфигурациях подов, компиляция останавливается с ошибкой подписания.
Как устранить конфликты подписи фреймворков CocoaPods без изменения исходного файла Podfile?
Если изменение главного файла `Podfile` невозможно, разработчики могут выбрать конкретную цель пакета ресурсов в проекте `Pods` в Xcode, перейти в раздел `Build Settings` и вручную установить для параметра `Code Signing Identity` пустое значение (`""`), а для `Code Signing Allowed` — значение `NO`. Тем не менее, автоматизация этого процесса с помощью локального хука `post_install` в Podfile является рекомендуемым долгосрочным решением.
Каков правильный способ ручного встраивания PrivacyInfo.xcprivacy в сборки XCFramework?
При ручном импорте XCFramework файл `PrivacyInfo.xcprivacy` должен находиться внутри каждого применимого варианта фреймворка для конкретной платформы (например, `MySDK.xcframework/ios-arm64/MySDK.framework/PrivacyInfo.xcprivacy`), а не помещаться в корневой каталог контейнера XCFramework. Xcode агрегирует декларации из манифестов конфиденциальности, обнаруженных в приложении и связанных пакетах SDK/фреймворков, при создании отчета о конфиденциальности.

Резюме и фреймворк принятия решений

Эффективный импорт iOS SDK требует выбора подходящего механизма зависимостей для цепочки инструментов проекта с одновременным смягчением требований к строгой подписи кода в Xcode. Использование CocoaPods с локальным хуком post_install позволяет решить проблемы с подписанием затронутых пакетов ресурсов, в то время как ручное встраивание XCFramework обеспечивает прямой контроль над артефактами сборки.

Поскольку Apple продолжает совершенствовать правила проверки App Store Connect, поддержание соответствия клиентских зависимостей стандартам манифестов конфиденциальности остается критически важным. Развертывая обновленные версии SDK и поддерживая автоматизированные хуки Podfile, инженерные команды сокращают количество повторяющихся сборок и повышают стабильность интеграции.

Разработчики, готовые инициализировать ключ своего проекта, могут зарегистрироваться в консоли разработчика OpoInstall или ознакомиться с полным руководством по внедрению мобильной атрибуции для получения дополнительных рекомендаций по платформам.

Связанные материалы

Share this article