如何为 iOS App 实现 PrivacyInfo.xcprivacy?实现 PrivacyInfo.xcprivacy 需要在您的应用或 SDK Target 中添加一个有效的隐私清单,为所使用的任何受保护原因 API(如 User Defaults 或系统引导时间)声明经批准的原因代码,并验证第三方依赖项是否满足与其分发形式相关的隐私清单和签名要求。
隐私清单(
PrivacyInfo.xcprivacy)是捆绑在 iOS App 和第三方 SDK 中的标准化属性列表文件,用于声明数据收集类别、跟踪域配置以及访问 Apple 指定的受保护原因 API 的经批准的正当理由。从 2024 年 5 月 1 日起,提交至 App Store Connect 的 App 必须包含应用代码(包括适用的第三方 SDK 代码)所使用的受保护原因 API 的批准原因。
| 术语 | 定义 |
|---|---|
| PrivacyInfo.xcprivacy | Apple 用于声明 App 和 SDK 隐私规范的标准化属性列表格式。 |
| Required Reason APIs | 需要明确提供正当理由代码的特定平台 API(如 User Defaults 或磁盘空间)。 |
| Resource Bundle Signing | 应用于生成的资源包 Target 的构建系统代码签名行为,在某些 Xcode 和 CocoaPods 配置中可能需要进行排查和处理。 |
| Privacy Report | 由 Xcode 15+ 生成的汇总 PDF 摘要,结合了在归档 App 和链接的 SDK 中发现的隐私清单声明。 |
理解 iOS SDK 的 Apple 隐私清单要求
隐私清单的架构:主应用清单与嵌入式 SDK 清单
Apple 的隐私清单框架在 iOS 软件供应链中建立了模块化的透明度模型。Apple 没有要求宿主应用手动审计和声明每个导入库的内部实现细节,而是将隐私治理划分为不同的层级:
- 主应用清单:涵盖第一方数据收集、App 级别的跟踪域,以及直接由主应用 Target 代码调用的受保护原因 API。
- 嵌入式 SDK 清单:受保护原因 API 声明必须由使用这些 API 的 App 或第三方 SDK 代码所有。对于可执行文件和动态库,包含该可执行文件或库的 Bundle 必须包含相关的隐私清单;第三方 SDK 不能依赖宿主应用的清单来报告该 SDK 对受保护原因 API 的使用情况。
- 自动化依赖项聚合:在 Xcode 15 或更高版本中归档应用程序时,构建系统会遍历依赖项图,发现所有捆绑的
PrivacyInfo.xcprivacy文件,并将它们聚合为单个统一的隐私报告。

四个根配置键
每个 PrivacyInfo.xcprivacy 文件都结构化为一个 XML 属性列表字典,包含最多四个根级键:
NSPrivacyTracking(布尔值):声明 App 或 SDK 是否根据 Apple App 跟踪透明度 (ATT) 的定义,使用从 App 收集的数据进行跟踪。NSPrivacyTrackingDomains(字符串数组):列出 App 或 SDK 连接的、参与跟踪的互联网域名。如果用户未授予 ATT 授权,iOS 将阻止对该数组中声明的域名的网络连接。如果 App 或 SDK 不连接到跟踪域名,则可以省略此键。NSPrivacyCollectedDataTypes(字典数组):报告 App 或 SDK 收集的关于使用 App 的人员的 Apple 定义的数据类别,同时报告该数据是否与用户身份关联、是否用于跟踪,以及收集该数据的业务目的。NSPrivacyAccessedAPITypes(字典数组):声明二进制文件调用的 Apple 指定的受保护原因 API,并附带经批准的字符串原因代码。

App Store Connect 引入强制执行与错误诊断
App Store Connect 在二进制文件引入期间会强制执行隐私清单检查:
- 缺少 API 声明 (
ITMS-91053):当编译后的二进制文件或链接库调用了受保护原因 API 符号,但NSPrivacyAccessedAPITypes中缺少相应的类别键时触发。 - 无效的原因代码声明:当清单为特定 API 类别声明了未经批准、格式错误或已弃用的原因字符串时发生。
- 缺少必需的第三方 SDK 清单:在 Apple 当前针对列出的 SDK 的第三方 SDK 要求中定义的提交场景中强制执行,要求二进制分发同时具备隐私清单和有效的数字签名。
集成客户端归因和深度链接的开发者可以查阅 iOS SDK 集成文档以获取有关清单声明的技术规范。
另请参阅:iOS SDK ──> 移动归因架构
受保护原因 API 类别与批准的原因代码
五个受保护原因 API 类别
根据 Apple Developer Technote TN3183,Apple 定义了五个需要在 NSPrivacyAccessedAPITypes 中提供明确正当理由代码的特定 API 类别。移动 SDK 和 iOS 应用通常会与其中四个主要类别交互:
NSPrivacyAccessedAPICategoryUserDefaults:通过UserDefaults或NSUserDefaults访问本地应用设置。NSPrivacyAccessedAPICategorySystemBootTime:使用系统启动 API(如sysctl(KERN_BOOTTIME)或systemUptime)测量经过的时间或时间戳。NSPrivacyAccessedAPICategoryDiskSpace:通过statfs、statvfs或volumeAvailableCapacityKey检查文件系统容量。NSPrivacyAccessedAPICategoryFileTimestamp:通过stat、getattrlist或contentModificationDateKey检查文件创建或修改日期。NSPrivacyAccessedAPICategoryActiveKeyboards:检查活跃的自定义键盘扩展(主要由专门的键盘实用工具使用)。
常见 SDK 用例的选定批准原因代码映射
下表重点关注通用移动 SDK 中常见的一些类别;有关完整的原因列表(包括 Active Keyboards),请参考 Apple 的最新文档。为遵守 Apple 指南,开发者必须选择与其实际运行时数据使用严格相符的原因代码:
| API 类别键 | 批准的代码 | Apple 官方对齐的目的 |
|---|---|---|
NSPrivacyAccessedAPICategoryUserDefaults |
CA92.1 |
读取和写入仅可由 App 本身访问的数据 |
NSPrivacyAccessedAPICategoryUserDefaults |
1C8F.1 |
读取和写入仅在同一 App Group 内部共享的数据 |
NSPrivacyAccessedAPICategoryUserDefaults |
C56D.1 |
向宿主 App 提供键值功能的第三方 SDK 包装器 |
NSPrivacyAccessedAPICategorySystemBootTime |
35F9.1 |
测量 App 内发生事件之间经过的时间或处理计时器 |
NSPrivacyAccessedAPICategorySystemBootTime |
8FFB.1 |
计算 App 内发生的事件的绝对时间戳 |
NSPrivacyAccessedAPICategoryDiskSpace |
E174.1 |
在写入文件前检查磁盘空间,如果空间不足则修改 App 行为 |
NSPrivacyAccessedAPICategoryDiskSpace |
85F4.1 |
访问磁盘空间信息以向用户显示可用容量 |
NSPrivacyAccessedAPICategoryFileTimestamp |
C617.1 |
访问 App 容器、App Group 或 CloudKit 容器内的文件元数据 |
NSPrivacyAccessedAPICategoryFileTimestamp |
3B52.1 |
访问由用户明确选择的文件或目录的元数据 |
NSPrivacyAccessedAPICategoryFileTimestamp |
0A2A.1 |
仅代表宿主 App 访问文件时间戳的第三方 SDK 包装器 |

构建示例 PrivacyInfo.xcprivacy 属性列表
配置数据收集类型
NSPrivacyCollectedDataTypes 数组报告了 App 或 SDK 收集的关于使用 App 的人们的 Apple 定义的数据类别,同时报告了该数据是否与用户身份关联、是否用于跟踪,以及收集该数据的业务目的:
NSPrivacyCollectedDataType:标准的 Apple 字符串标识符(例如NSPrivacyCollectedDataTypeDeviceID)。NSPrivacyCollectedDataTypeLinked:一个布尔值,指示数据是否与单个用户的身份关联。NSPrivacyCollectedDataTypeTracking:一个布尔值,指示数据是否用于跨 App 跟踪。NSPrivacyCollectedDataTypePurposes:标准目的字符串数组(例如NSPrivacyCollectedDataTypePurposeAnalytics)。
声明跟踪域名
如果 SDK 或应用程序根据 ATT 定义参与跟踪,则所有相应的跟踪域名都必须在 NSPrivacyTrackingDomains 下声明。如果用户未授予跟踪授权,iOS 将阻止对所声明域名的网络连接。如果 App 或 SDK 不参与跟踪,则应将 NSPrivacyTracking 设置为 false 并可以省略 NSPrivacyTrackingDomains。
下面的属性列表配置展示了一个示例 PrivacyInfo.xcprivacy 架构。请仅包含反映您应用实际实现的类别和原因:
```xml
<?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>NSPrivacyCollectedDataTypes</key>
<array>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeDeviceID</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
</array>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>E174.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
</array>
</dict>
</array>
</dict>
</plist>
解决 CocoaPods 资源包代码签名错误
根本原因:Xcode 15 和 16 中的资源包签名失败
在 Xcode 15 或 16 中通过 CocoaPods 集成依赖项时,开发者经常会遇到编译中断:
Signing for "libOpoInstallSDK-OPPrivacy" requires a development team. Select a development team in the Signing & Capabilities editor.
此构建失败是一个 Xcode 和 CocoaPods 集成问题:
- 传统的
.a静态库不能直接包含诸如PrivacyInfo.xcprivacy之类的资源。Apple 建议将静态 SDK 代码和资源一起打包在静态框架(Static Framework)中。 - 某些 CocoaPods 集成改为生成独立的资源包 Target,以便将资源与静态库一起分发。
- 某些由 CocoaPods 生成的资源包 Target 可能会继承签名配置,从而导致 Xcode 构建在请求开发团队时暂停。这是一个构建系统集成问题,而不是
PrivacyInfo.xcprivacy架构要求。
在 Podfile 中应用针对性的构建系统变通方法
为了在自动化构建中解决此错误,开发者可以在项目 Podfile 中使用带作用域的 post_install 钩子。由于这是针对非可执行资源包的构建系统变通方法,团队应将其限定在特定的受影响 Bundle Target 内,或在全局应用更改之前验证受影响的依赖项。
下面的 Ruby 脚本演示了如何遍历 CocoaPods Target 并在指定的资源包 Target 上禁用签名:
post_install do |installer|
# 指定在没有开发团队时遇到签名错误的非可执行资源包 Target
target_bundle_names = [
'libOpoInstallSDK-OPPrivacy'
]
installer.pods_project.targets.each do |target|
if target.respond_to?(:product_type) &&
target.product_type == "com.apple.product-type.bundle" &&
target_bundle_names.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
end
在 Xcode 中审计并生成聚合隐私报告
通过 Xcode Archive Organizer 生成统一隐私报告
为确保在提交二进制文件之前正确声明了所有第一方 Target 和第三方依赖项:
- 在 Xcode 15 或更高版本中打开您的项目。
- 选择 Product > Archive 以创建发布归档。
- 在 Xcode Organizer 中,右键单击(或按住 Control 键单击)该归档并选择 Generate Privacy Report。
- 保存并检查生成的 PDF 报告,以确认所有受保护原因 API、数据类别和第三方 SDK 清单都准确无误。
命令行静态分析:提交前启发式扫描
开发团队可以在持续集成 (CI/CD) 管道中实施启发式提交前审计,通过使用 nm 和 otool 扫描编译后的二进制文件中的受限符号:
# 扫描解压的应用二进制文件以查找候选的受保护原因 API 符号
nm -u /path/to/Payload/YourApp.app/YourApp | grep -E 'sysctl|statfs|statvfs|getattrlist|NSUserDefaults'
# 检查嵌入式 Framework 和 Bundle 是否包含 PrivacyInfo.xcprivacy 清单
find /path/to/Payload/YourApp.app -name "PrivacyInfo.xcprivacy"
符号的存在本身并不能确定适用的批准原因;在修改清单之前,请检查实际的调用路径和用例。团队必须使用 Xcode 的 Generate Privacy Report 和 App Store Connect 预检进行权威验证。

诊断矩阵:App Store 隐私清单被拒的根本原因
| 失败模式 / 错误代码 | 底层根本原因 | 观察到的系统行为 | 推荐的修复方案 |
|---|---|---|---|
缺少 API 声明 (ITMS-91053) |
二进制文件调用了受限 API,但清单中省略了该类别 | App Store Connect 上传警告或被拒 | 声明匹配的 API 类别和有效的原因代码 |
| 无效的原因代码 | 指定的原因代码未获得 Apple 对该类别的批准 | App Store Connect 拒绝提交 | 更新 XML 以使用 Apple 规范中批准的原因字符串 |
| 缺少第三方 SDK 清单 | 列出的第三方 SDK 依赖项缺少嵌入式清单 | App Store Connect 标记缺少 SDK 清单 | 将依赖项升级到提供 PrivacyInfo.xcprivacy 的版本 |
| 资源包代码签名错误 | CocoaPods 生成了一个没有签名团队的资源包 Target | Xcode 编译在构建期间暂停 | 评估失败的 Bundle Target 并应用有针对性的 Podfile 签名变通方法 |
| 未声明的跟踪端点 | App 连接了未在 NSPrivacyTrackingDomains 中列出的跟踪服务器 |
对于 App 的跟踪行为而言,隐私配置不完整 | 在 NSPrivacyTrackingDomains 下列出所有跟踪端点 |
常见问题解答 (FAQ)
每个第三方 SDK 都需要它自己的 PrivacyInfo.xcprivacy 文件吗?
如果 App 使用了 UserDefaults 但未声明批准的原因,会发生什么?
应用程序可以为一个 API 类别声明多个原因吗?
总结与决策框架
Apple 的隐私清单框架强制推行了 iOS 软件供应链的透明度。为确保顺畅的 App Store 提交,开发团队需要审计第一方代码中的受保护原因 API 使用情况,验证第三方 SDK 依赖项是否满足适用于其 API 使用的隐私清单要求,并妥善管理 CocoaPods 资源包签名。
有关特定于产品的隐私清单声明,请查阅 OpoInstall 文档,并将发布的清单与应用的实际集成情况以及 Apple 的当前要求进行对比。
相关资料
-
核心概念:隐私清单、受保护原因 API、资源包代码签名、隐私报告、App Store 合规性
-
技术栈:Xcode 15+、CocoaPods 依赖管理器、Swift Package Manager、OpoInstall iOS SDK
-
行业标准:Apple 隐私清单规范、App Store 审核指南第 5.1.1 节
-
API 与配置:
PrivacyInfo.xcprivacy、NSPrivacyAccessedAPITypes、Podfilepost_install钩子
官方文档
Share this article



