如何在 iOS SDK 設定中解決 CocoaPods Framework 簽章問題

opoinstall
2026-11-12
5 min read

整合 iOS SDK 時,該如何修復 CocoaPods framework 簽章錯誤? 請先診斷觸發「Development Team」錯誤的受影響非執行時期資源包 (resource-bundle) 目標,然後套用範圍限定於特定目標的 CocoaPods post_install 覆寫,而不是在所有 bundle 之間全域停用簽章。

在受影響的 CocoaPods/Xcode 設定中,產生的資源包目標可能會繼承導致 Xcode 要求開發團隊 (Development Team) 的簽章設定。若要解決這些建置失敗的問題,需要設定自訂的 Podfile post_install 建置鉤子,以停用非執行時期資源子目標的簽章需求,或執行手動 XCFramework 嵌入協定。

名詞 定義 相關實體 搜尋意圖角色
iOS SDK 一個已編譯的 framework,可在 iOS 上啟用行動裝置歸因與深度連結。 Xcode Framework 目標 資訊型 / 技術型
CocoaPods 適用於 Swift 與 Objective-C 專案的應用程式層級相依性管理工具。 Podfile 建置鉤子 技術型 / 資訊型
隱私權清單 詳細說明應用程式或 framework 隱私權實務的結構化清單。 PrivacyInfo.xcprivacy 技術型 / 合規型

為什麼 Xcode 15 與 16 的程式碼簽章規則會破壞 iOS SDK CocoaPods 建置

Xcode 建置工具鏈與資源包簽章

從 Xcode 15 開始並延續至 Xcode 16,Xcode 建置系統的修改改變了程式碼簽章設定向下傳播至所產生子目標的方式。在受影響的 Xcode 與 CocoaPods 設定中,封裝了諸如 PrivacyInfo.xcprivacy、資源目錄 (asset catalogs) 或本地化字串等資源的非執行時期資源包目標,可能會繼承促使 Xcode 要求開發團隊的程式碼簽章設定。

此問題代表 CocoaPods 目標產生過程中的建置系統整合不匹配,而非 Apple 強制要求每個獨立、非執行時期資源包都必須具備獨立程式碼簽章的嚴格政策。

編譯錯誤剖析:針對目標的簽章需要開發團隊 (Development Team)

使用 CocoaPods 整合相依性時,相依性管理工具會產生一個獨立的 Pods.xcodeproj 專案,其中包含每個 pod 及其相關資源包的隔離目標。在建立封存檔 (archive) 或模擬器編譯期間,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 圖形介面 (GUI) 中手動設定開發團隊只是暫時的。重新執行 pod install 或在乾淨的 CI/CD 工作站上建置會覆寫專案檔案,導致建置錯誤再次發生。

與可執行 framework 簽章隔離的 iOS 資源包簽章錯誤。

CocoaPods 子目標如何為隱私權清單包繼承未簽章屬性

某些 CocoaPods podspec 透過產生的資源包子目標(例如透過 resource_bundles 宣告)來封裝隱私權清單,而其他則將清單隨附於第三方 framework 或直接的資源宣告中。

在受影響的 CocoaPods 設定中,產生的資源包子目標可能缺少可用的 DEVELOPMENT_TEAM 值,或是繼承了會導致 Xcode 要求該值的簽章設定。因此,雖然主應用程式目標是以有效的描述檔案 (provisioning profile) 進行建置,但巢狀的資源包子目標可能會觸發 Xcode 的程式碼簽章預先檢查。解決此問題需要在 Podfile 層級進行針對性的因應措施,或轉為手動嵌入 framework。

如何設定 Podfile 建置鉤子以修復 Framework 包簽章錯誤

了解 CocoaPods post_install 執行鉤子

CocoaPods 在 Podfile 中提供了一個名為 post_install 的 Ruby 基礎生命週期鉤子。此鉤子會在 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

範圍限定的 CocoaPods post install 鉤子僅修改受影響的資源包。

跨 Xcode 封存與模擬器建置目標驗證 CI/CD 相容性

將範圍限定的建置鉤子附加到 Podfile 後,執行 pod install 以將更新後的設定套用至 Pods.xcodeproj。模擬器建置通常比裝置封存檔具有較不嚴格的分發簽章要求,但工程團隊應分別在本地模擬器執行、CI/CD 自動化測試執行以及 Xcode 發布封存設定中驗證受影響的目標設定。

用於程式碼簽章驗證的診斷檢查指令

檢查目標建置設定與程式碼簽章身分識別

在建置伺服器上診斷間歇性簽章失敗時,開發人員可以直接透過終端機指令查詢 Xcode 的建置設定。這有助於驗證 Podfile post_install 鉤子是否成功清除了受影響子目標的程式碼簽章要求。請注意,也可以在 Xcode 中直接檢查 Pods.xcodeproj 內個別目標的建置設定,以驗證目標特定的有效值。

從專案根目錄執行以下指令:

# 檢查目標工作區的程式碼簽章建置設定
xcodebuild \
  -workspace YourApp.xcworkspace \
  -scheme YourApp \
  -configuration Release \
  -showBuildSettings | grep -E "(CODE_SIGN|DEVELOPMENT_TEAM)"

稽核 Xcode 封存包與簽章完整性

產生封存檔後,請檢查已編譯的應用程式套件,以確認隱私權清單已正確放置,且 framework 二進位檔維持簽章完整性。

在解壓縮的 IPA 內(位於 Payload/YourApp.app 中)或 Xcode .xcarchive 路徑(Products/Applications/YourApp.app)內執行這些診斷終端機指令:

# 檢查解壓縮 IPA 套件內隱私權清單的存在性
find Payload/YourApp.app -name "PrivacyInfo.xcprivacy" -print

# 對於動態嵌入的 framework,驗證 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 封存驗證會檢查隱私權清單放置位置與嵌入式 framework 簽章。

如何透過 CocoaPods 相依性管理工具匯入 iOS SDK

透過 pod ‘libOpoInstallSDK’ 設定目標專案 Podfile

透過 CocoaPods 整合行動裝置歸因與深度連結平台 OpoInstall,代表 iOS 應用程式的標準相依性管理方法。目前的 CocoaPods 發布版本根據其 podspec 處理 SDK 的連結與封裝資源。當 SDK 目前的 CocoaPods 整合或專案架構需要時,請包含 use_frameworks!。

若要新增相依性,請開啟根目錄的 Podfile 並指定目標相依性:

target 'YourAppTarget' do
  use_frameworks!
  
  # 匯入 OpoInstall iOS 歸因 SDK
  pod 'libOpoInstallSDK'
end

執行相依性取得與驗證工作區完整性

使用終端機從專案根目錄執行安裝指令:

pod install --repo-update

順利完成後,CocoaPods 會產生或更新 .xcworkspace 檔案。開發人員必須關閉標準的 .xcodeproj 檔案,並在 Xcode 中開啟 .xcworkspace 檔案。檢查 Pods 專案資料夾,以驗證 libOpoInstallSDK 及其相關的 OPPrivacy bundle 目標是否出現在 Pods 目標清單下方。

在 Swift 專案架構中初始化 SDK 引擎

連結 framework 後,請在應用程式生命週期代理程式 (delegate) 內初始化 SDK。請在確切 SDK 版本所文件化的生命週期點初始化 SDK;目前的公開範例從 application(_:didFinishLaunchingWithOptions:) 進行初始化,以擷取冷啟動通用連結 (Universal Link) 參數與動態安裝酬載 (payload)。請對照出貨的確切 OpoInstall SDK 版本,驗證代理程式協定與資料模型型別名稱(例如 OpoinstallData 或 OpoInstallData)。

開發人員可以查閱完整的 iOS 歸因 SDK 文件以取得詳細的代理程式方法定義與動態參數回呼簽章。

以下實作片段說明如何在現代 Swift 程式碼庫中遵循 OpoInstallDelegate 並觸發 SDK 初始化:

// AppDelegate.swift - OpoInstall iOS SDK 初始化
// 放置於您的 iOS 應用程式代理程式內

import UIKit
import libOpoInstallSDK

@main
class AppDelegate: UIResponder, UIApplicationDelegate, OpoInstallDelegate {

    var window: UIWindow?

    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        
        # 透過代理程式監聽器初始化 OpoInstall SDK
        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 專案目標的手動 Framework 匯入工作流程

何時在企業建置環境中選擇手動匯入而非 CocoaPods

雖然 CocoaPods 簡化了套件管理,但某些企業開發環境會強制執行嚴格的安全性或建置環境限制。在下列情況下,建議採用手動 framework 整合:

  • 儲存庫隔離:建置系統限制對外網際網路連線,防止編譯期間進行 pod install 相依性擷取。
  • 建置管線速度:排除 CocoaPods 分析與指令碼執行步驟可縮短 CI/CD 編譯時間。
  • 直接二進位檔控制:安全性合規政策要求在將精確的 .xcframework 產出物納入專案之前,必須進行靜態二進位檔分析。

下載並嵌入 XCFramework 產出物

若要在沒有相依性管理工具的情況下手动匯入 SDK,請下載 最新 iOS SDK framework 套件。解壓縮分發封存檔以尋找已編譯的 OpoInstallSDK.xcframework 目錄。

若要在嵌入前識別 XCFramework 片段是靜態還是動態,請在終端機中執行 file 指令:

# 查詢二進位架構片段型別
file OpoInstallSDK.xcframework/ios-arm64/OpoInstallSDK.framework/OpoInstallSDK

請依照下列步驟將二進位檔整合至 Xcode:

  • 步驟 1:在 Xcode 中開啟您的主應用程式專案。
  • 步驟 2:將 OpoInstallSDK.xcframework 目錄拖曳到 Xcode 專案導覽器 (Project Navigator) 中的主要目標 framework 群組下方。
  • 步驟 3:在對話方塊提示中,勾選必要時複製項目 (Copy items if needed),並在新增至目標 (Add to targets) 下方選取您的主要應用程式目標。

設定「連結二進位檔與程式庫」及「Framework 搜尋路徑」

導覽至 Xcode 中的應用程式目標設定:

  • Build Phases:展開Link Binary With Libraries區段。確認已列出 OpoInstallSDK.xcframework。
  • Build Settings:搜尋Framework Search Paths (FRAMEWORK_SEARCH_PATHS)。確保包含手動新增之 framework 的目錄路徑存在。
  • 系統相依性:僅新增您正在整合之確切 SDK 版本所記載的 Apple 系統 framework(例如 AdSupport.framework 或 WebKit.framework)。請勿新增未經證實的舊版 framework。

為動態與靜態二進位檔設定嵌入與簽章政策

選取應用程式目標並導覽至General分頁。尋找Frameworks, Libraries, and Embedded Content區段:

靜態與動態 XCFramework 二進位檔遵循不同的 iOS 嵌入與簽章路徑。

  • 動態 Framework (Dynamic Frameworks):將嵌入選項設為Embed & Sign。動態 framework 必須位於最終應用程式包的 Frameworks 目錄中,以便動態連結器 (dyld) 可以在執行時期載入它們,且 Xcode 會在封存期間套用您開發團隊的程式碼簽章。
  • 不含資源的靜態 Framework (Static Frameworks without Resources):連結二進位檔即足夠,且通常不需要嵌入 framework,因為靜態程式碼是直接編譯到主應用程式可執行檔中。
  • 包含資源(包含隱私權清單)的靜態 Framework (Static Frameworks with Resources):請遵循 SDK 供應商的分發指南。針對為封裝嵌入資源而建置的 Xcode 15+ 靜態 framework,Apple 記載了透過 Embed & Sign 新增 framework 的做法;Xcode 會省略已靜態連結的可執行二進位檔,同時保留並簽署 framework 包及其嵌入資源。

大小事:排解 CocoaPods 中 PrivacyInfo.xcprivacy 簽章衝突

第三方 Framework 相依性的 Apple 隱私權清單要求

第三方 SDK 可能需要包含 PrivacyInfo.xcprivacy 清單,這取決於其 API 使用方式、資料收集實務、追蹤行為,以及該 SDK 是否出現在 Apple 公布受明確清單要求約束的 SDK 清單中。

目前的 OpoInstall 發布版本包含 PrivacyInfo.xcprivacy 清單;開發人員應在封存之前,針對出貨的特定 SDK 版本與 Apple 目前的提交指南來驗證其宣告。

解決重複的隱私權清單資源衝突

在建置包含多個第三方相依性的應用程式時,Xcode 會在已封存的應用程式和已連結的 SDK 包中尋找隱私權清單,並在產生用於稽核合併隱私權宣告的 Xcode 隱私權報告時彙總其宣告。

如果專案不正確地將重複的隱私權清單檔案直接包含在主目標的複製包資源 (Copy Bundle Resources) 階段中,Xcode 可能會發出建置警告或錯誤:

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

若要解決此衝突:

  • Framework 清單位置:對於 iOS XCFramework,PrivacyInfo.xcprivacy 必須位於每個適用的平台特定 framework 變體內(例如 OpoInstallSDK.xcframework/ios-arm64/OpoInstallSDK.framework/PrivacyInfo.xcprivacy),而不是放置在 XCFramework 根容器目錄中。
  • 主應用程式資源:將主機應用程式隱私權宣告保留在主目標的資源中,同時允許 SDK framework 變體內部管理其各自的清單檔案。

驗證 PrivacyInfo.xcprivacy 內的「所需原因 API (Required Reason API)」宣告

檢查隱私權清單的內容,以驗證所有宣告的 API 類別是否符合 Apple 官方的所需原因 API 規格。在 Xcode 中以屬性列表 (Property List) 或原始 XML 形式開啟 PrivacyInfo.xcprivacy。宣告應嚴格對應至必要的 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>

僅包含與 SDK 實際實作要求相符的 API 類別與核准的原因代碼。

驗證最終的 App Store Connect IPA 提交

在將應用程式更新提交至 App Store Connect 之前,請先在本機驗證已編譯的 IPA 封存檔:

  • 步驟 1:在 Xcode 中,選取Product > Archive。
  • 步驟 2:封存完成後,按一下 Organizer 視窗內的Validate App。
  • 步驟 3:Xcode 會針對 Apple 驗證伺服器檢查嵌入的 framework 簽章、描述檔案授權 (provisioning entitlements) 以及隱私權清單結構描述。

驗證成功表示封存檔已通過該提交前的驗證階段;這是在進行 TestFlight 或正式環境提交之前必要的建置驗證步驟。

CocoaPods 與手動 iOS Framework 匯入的比較分析

### 維護、簽章隔離與建置自動化的取捨

在 CocoaPods 與手動 framework 整合之間做出選擇,涉及評估團隊工作流程、建置伺服器功能以及相依性維護負荷。雖然 CocoaPods 自動化版本更新,但 Xcode 版本升級可能需要更新 Podfile post_install 鉤子以符合不斷變更的 Apple 簽章政策。

下表提供這兩種匯入策略的詳細技術比較:

功能維度 CocoaPods 相依性管理工具 手動 Framework 嵌入 (.xcframework)
版本維護 透過 pod update 自動化 手動二進位檔下載與替換
建置設定組態 透過 Ruby Podfile 鉤子以指令碼編寫 直接在 Xcode 目標設定中進行設定
程式碼簽章管理 可能需要範圍限定的 post_install 因應措施 在目標 Framework 設定中直接控制
隱私權清單處理 透過 pod 資源管理;Xcode 會將發現的清單彙總到隱私權報告中 在每個 framework 變體內進行驗證
CI/CD 管線摩擦 低(需要 Podfile.lock 同步) 低(Framework 儲存在版本控制中)

評估企業行動團隊間的相依性管理策略

對於已經標準化採用 Podfile 基礎相依性管理的團隊而言,CocoaPods 仍然是一個實際的選項,因為它具有自動化相依性解析與透過 Podfile.lock 集中版本鎖定的優點。納入範圍限定的 Ruby 簽章覆寫指令碼有助於解決跨團隊工作站與 CI/CD 建置環境的目標層級簽章阻礙。

常見問題 (FAQ)

為什麼 Xcode 會回報 CocoaPods 中資源包的簽章錯誤?
在某些 Xcode 15/16 與 CocoaPods 設定中,產生的非執行時期資源包目標可能會繼承導致 Xcode 要求開發團隊的簽章設定。如果這些子目標在產生的 pod 設定中繼承了不完整的程式碼簽章屬性,編譯就會因簽章錯誤而中止。
如何在不修改原始 Podfile 的情況下解決 CocoaPods framework 簽章衝突?
如果無法修改主 `Podfile`,開發人員可以在 Xcode 的 `Pods` 專案下選取特定的資源包目標,導覽至 `Build Settings`,然後手動將 `Code Signing Identity` 設為空白 (`""`),並將 `Code Signing Allowed` 設為 `NO`。不過,透過範圍限定的 Podfile `post_install` 鉤子自動化此程序是建議的長遠解決方案。
在 XCFramework 建置中手動嵌入 PrivacyInfo.xcprivacy 的正確方法是什麼?
手動匯入 XCFramework 時,`PrivacyInfo.xcprivacy` 必須位於每個適用的平台特定 framework 變體內(例如 `MySDK.xcframework/ios-arm64/MySDK.framework/PrivacyInfo.xcprivacy`),而不是放置在 XCFramework 容器根目錄中。當產生隱私權報告時,Xcode 會彙總在應用程式與已連結的 SDK/framework 包中所發現隱私權清單的宣告。

總結與決策框架

有效率地匯入 iOS SDK 需要為您的專案工具鏈選取合適的相依性機制,同時減輕 Xcode 程式碼簽章的嚴格性。使用搭配範圍限定 post_install 鉤子的 CocoaPods 可以解決受影響的資源包簽章失敗問題,而手動 XCFramework 嵌入則提供對建置產出物的直接控制。

隨著 Apple 持續精進 App Store Connect 驗證規則,保持用戶端相依性符合隱私權清單標準依然至關重要。透過部署更新的 SDK 版本並維護自動化 Podfile 鉤子,工程團隊可以減少重複發生的建置阻礙並提升整合一致性。

準備好初始化專案金鑰的開發人員可以在 OpoInstall 開發人員主控台註冊,或查閱完整的 行動歸因實作參考以取得額外的平台指南。

相關資料

Share this article