1. 为什么iOS 17的隐私清单让你我如此“上头”?
最近几个月,但凡还在维护iOS App的开发者,估计都被一个叫 PrivacyInfo.xcprivacy 的文件搞得有点头大。苹果在去年WWDC上宣布,从2024年5月1日开始,提交到App Store的新App和App更新,都必须包含这个隐私清单文件。这可不是一个简单的“新增文件”操作,它要求你清晰地声明App及其使用的所有第三方库,到底访问了哪些用户隐私数据,以及为什么要访问。
我刚开始接触这个要求时,也觉得有点懵。心想,不就是加个文件嘛,能有多复杂?但真正上手后才发现,这里面的坑一个接一个。主工程要加,第三方库也要加;API要声明,使用理由(Reason)要选对;更头疼的是,当你引入多个第三方库时,它们可能和你的主工程“打架”,报出那个经典的 multiple commands produce privacyinfo.xcprivacy 错误。我身边好几个朋友的项目,都因为这个审核被拒了,来回折腾了好几天。
所以,今天我就想以一个踩过坑的“过来人”身份,和大家系统地聊聊这件事。我们不只讲主工程怎么配,更要深入到那些让人又爱又恨的第三方库,从自动化检测到手动填坑,给你一套从项目根目录到最深层依赖的完整解决方案。目标只有一个:让你下次提交审核时,关于隐私清单的部分能一次通过,把时间省下来去喝杯咖啡。
简单来说,PrivacyInfo.xcprivacy 文件是苹果为了提升透明度,要求开发者提供的一份“隐私数据使用说明书”。它需要你列出所有被代码调用的、涉及隐私的API(比如访问相册、获取设备标识符、读取用户位置等),并为每一个API选择一个苹果预设的、准确的“使用理由”。这份清单会最终体现在App Store的隐私标签里,让用户对你的App如何收集和使用数据一目了然。这不仅是合规要求,更是建立用户信任的好机会。
2. 第一步:搞定自家“后院”——主工程隐私清单配置
万事开头难,我们先从自己完全可控的主工程开始。这一步的核心是:全面扫描 + 精准声明。你不能靠猜自己用了哪些隐私API,必须借助工具进行地毯式搜索。
2.1 选择合适的“侦察兵”:自动化检测工具实战
手动在几十万行代码里找API调用,无异于大海捞针。幸运的是,社区已经有开发者做出了很棒的工具。我强烈推荐使用那个在GitHub上开源的Python脚本,比如 update_privacy_info.py。它的原理是扫描你的项目源代码,匹配苹果官方定义的隐私API列表,然后生成报告和清单草稿。
具体操作起来非常简单。首先,确保你的电脑上安装了Python3。然后,打开终端,跟着我一步步来:
# 1. 克隆或下载工具仓库(假设你已经下载到本地)
cd /path/to/your/downloaded_tool_folder
# 2. 运行脚本,并指定你的Xcode项目根目录路径
python3 update_privacy_info.py /Users/你的用户名/Desktop/YourAppProject
运行成功后,工具通常会在你的项目目录下生成两个关键文件:一个是以 .txt 结尾的详细报告文件,另一个就是初版的 PrivacyInfo.xcprivacy 文件。报告文件你一定要仔细看,它会列出在哪些源代码文件里,具体调用了哪个隐私API。这是你后续核对和填写理由的基石。
2.2 解读报告与填充“使用理由”(Reason)
打开生成的 PrivacyInfo.xcprivacy 文件,你会发现它是一个结构化的 .plist 文件。里面已经根据扫描结果,填充好了 NSPrivacyAccessedAPITypes 数组。每个API类型下,会有一个 NSPrivacyAccessedAPITypeReasons 数组,但里面的Reason(理由)通常是空的或者需要你确认。
这才是最考验理解的一步。 你不能随便选个理由填上,必须确保理由与你的App实际功能严格匹配。苹果提供了详细的理由列表,每个理由都有唯一的编码(如 CA92.1, 35F9.1)。选错了,审核很可能被拒。
这里我分享一个超级好用的在线工具:privacymanifest.dev。你不需要去硬啃苹果那冗长的文档,在这个网页上,你可以通过搜索API名称,直观地看到所有可用的理由及其描述。比如,你的报告显示使用了 UserDefaults 来存储用户的登录状态,那么对应的理由就应该是 CA92.1(在设备上存储非敏感信息,以支持应用程序的基本功能)。把这个编码复制下来,粘贴到你工程里 PrivacyInfo.xcprivacy 文件中对应API的 NSPrivacyAccessedAPITypeReasons 数组里。
2.3 将清单文件集成到Xcode工程
生成了正确的 PrivacyInfo.xcprivacy 文件后,你需要把它添加到Xcode项目中。
- 打开你的Xcode工程。
- 直接将这个文件拖拽到项目导航器的合适位置(通常放在项目根目录,与
Info.plist同级)。 - 在弹出的确认框中,务必勾选你的App主Target,确保它被包含在“Copy Bundle Resources”构建阶段中。
- 检查文件是否被正确引用:选中你的App Target,进入
Build Phases,查看Copy Bundle Resources里是否有这个文件。
完成这一步,恭喜你,主工程的“堡垒”已经初步建成。但这只是胜利的一半,真正的挑战往往来自那些你无法直接控制的“盟友”——第三方库。
3. 第二步:安抚“友军”——处理第三方库的隐私清单
如果说主工程是自己家,那第三方库就是请来的客人。客人也得遵守家里的新规矩(苹果的隐私政策)。苹果明确要求,如果你的App使用了其官方列表中的第三方SDK,或者任何SDK使用了需要声明的隐私API,那么该SDK也必须提供自己的 PrivacyInfo.xcprivacy 文件。
3.1 识别哪些第三方库需要行动
首先,你需要判断你的项目里有哪些库“中招”了。有两个主要途径:
- 依赖自动化工具的扫描报告:前面提到的那个Python脚本生成的
.txt报告文件,通常会指出哪些第三方库的代码包含了需要声明的API。这是一个很好的起点。 - 核对苹果官方列表:访问苹果开发者网站的“常见第三方SDK要求”页面。这里列出了第一批被明确点名的、广泛使用的SDK(例如:Adjust, Firebase Analytics, SDWebImage等)。如果你的项目里有列表中的库,那它肯定是需要隐私清单的。
3.2 分情况处理:等待更新 vs. 自行添加
确定了目标库之后,我们面临两种情形:
情形一:库作者已经更新。 这是最省心的。比如你用的 SDWebImage,其新版本(如 6.0.0 以上)已经内置了 PrivacyInfo.xcprivacy 文件。你只需要更新你的依赖到最新版本即可。对于CocoaPods用户,运行 pod update 库名;对于SPM用户,更新Package版本。
情形二:库作者尚未更新。 这在当前过渡期非常常见。我们不能干等,需要自己动手。操作思路是:将这个第三方库以“修改版”的形式引入项目,并为其添加隐私清单。
- 对于CocoaPods:你可以fork该库的GitHub仓库,在本地添加好
PrivacyInfo.xcprivacy文件,并修改其.podspec文件,通过resource_bundles或resources字段将这个隐私清单文件声明为资源。然后,在你的主项目的Podfile中,将对该库的引用指向你fork的仓库地址和分支。pod 'SomeLibrary', :git => 'https://github.com/你的用户名/SomeLibrary.git', :branch => 'add-privacy-manifest' - 对于SPM:你可以将Package的引用方式改为通过本地路径或你fork的仓库地址引入,然后在Package的Target资源设置中添加该文件。
3.3 避坑指南:解决“多份清单”冲突
在你为多个第三方库手动添加隐私清单,或者某些库的新版本也自带清单后,一个经典的编译错误很可能找上门来:
error: Multiple commands produce ‘PrivacyInfo.xcprivacy’
这个错误的意思是,在构建过程中,有多个Target(你的主App Target和某个或多个第三方库的Target)都生成了同名的 PrivacyInfo.xcprivacy 文件,并且它们都被尝试复制到最终的App Bundle中,导致了冲突。
解决方案的核心思路是:确保每个 PrivacyInfo.xcprivacy 文件只属于一个明确的Target,并且其他Target不重复包含它。
方案A(推荐):修改第三方库的构建配置。 如果你是自己fork并修改的第三方库,理想的做法是在库的工程配置里,确保其 PrivacyInfo.xcprivacy 文件仅被包含在该库自身的Bundle资源中,并且设置该文件不被复制到主App的Bundle里(通常通过设置 CODE_SIGNING_ALLOWED 为 NO 或调整Copy Phase实现)。但这要求你对库的构建系统比较熟悉。
方案B(实践中的快速解法):为主工程清单文件重命名。 这是一个经过验证有效的“偏方”。将你主工程中的 PrivacyInfo.xcprivacy 文件改个名字,比如改成 AppPrivacyInfo.xcprivacy。然后在Xcode中,选中你的App Target,进入 Build Settings,搜索 Privacy Manifest File 设置项,将它的值从默认的 PrivacyInfo.xcprivacy 改为你新的文件名 AppPrivacyInfo.xcprivacy。这样,编译器就能区分开主工程和第三方库的清单文件,从而避免冲突。我自己的项目就是用这个方法快速解决了问题。
4. 进阶策略与持续维护
隐私清单的适配不是一劳永逸的。随着App功能迭代和第三方库的更新,你需要建立持续的维护机制。
4.1 建立代码审查关卡
将隐私API的使用纳入代码审查流程。当团队成员新增代码时,如果涉及到访问相册、位置、联系人等敏感API,必须同时考虑是否需要更新 PrivacyInfo.xcprivacy 文件,并明确填写正确的使用理由。可以在团队Wiki或README中维护一个内部对照表,列出常用API及其对应的合规理由,方便查阅。
4.2 利用Xcode的静态分析
Xcode 15及更高版本增强了对隐私清单的静态分析能力。定期使用Xcode的 Product -> Analyze 功能对你的项目进行分析。它不仅能发现内存泄漏和逻辑错误,有时也会对隐私API的使用与隐私清单声明不一致的地方提出警告。把这些警告当成是审核前的“模拟考”,提前解决掉。
4.3 关注第三方库的动态
订阅你所用重要第三方库的GitHub Release、博客或社区动态。一旦它们发布了包含官方隐私清单的新版本,应尽快评估并升级。使用官方版本永远比自己维护一个fork要更可持续、更安全。你可以考虑在项目中建立一个简单的检查清单,记录每个第三方库的隐私清单状态(“已内置”、“需手动添加”、“待作者更新”),定期回顾。
4.4 最终提交前的完整检查清单
在打包上传App Store Connect之前,请务必对照以下清单做最后确认:
- 文件存在性:主工程的
PrivacyInfo.xcprivacy文件已正确添加到Target的Copy Bundle Resources中。 - 内容准确性:清单中声明的每一个API都在项目中被实际使用,且每一个使用理由都准确无误,与App功能描述相符。
- 第三方库覆盖:所有使用了隐私API的第三方库,都已通过升级或自行添加的方式,具备了隐私清单文件。
- 编译无冲突:项目可以正常编译,没有出现
multiple commands produce相关的错误。 - 归档验证:使用Xcode成功生成
.ipa归档文件后,可以右键选择“显示包内容”,查看Payload/YourApp.app目录下,是否包含了应有的隐私清单文件(可能有多个,分别来自主工程和不同的第三方框架Bundle)。
走完这一整套流程,你的App在隐私合规性上就已经做好了充分准备。这个过程确实有些繁琐,但换个角度看,它也在倒逼我们开发者更规范、更透明地处理用户数据。我自己的项目在按照这个流程处理后的第一次提交,就顺利通过了审核。希望这份结合了实战经验和避坑指南的总结,能帮你更从容地应对iOS 17的隐私新规,把更多精力聚焦在App功能的开发本身。如果在实际操作中遇到新的问题,不妨多看看苹果的官方文档和开发者论坛,社区的智慧总是无穷的。
126



被折叠的 条评论
为什么被折叠?



