ITMS-90683 错误:Expo 修复方法
作者:Mehdi Azizi
发布于 ,6分钟
ITMS-90683 表示 Info.plist 缺少用途说明。在 app.json 的 ios.infoPlist 中补上邮件提到的键,再重新构建即可。
ITMS-90683 是 Apple 的自动拒绝:它会在你上传构建后不久通过邮件发来,早于任何人工审核。意思是你的 Info.plist 文件里缺了一句话,用来解释 app 为什么要访问某项敏感数据。修复只需两步:把邮件里提到的键加到 ios.infoPlist,然后重新构建。
我在 Solys(我的小游戏闹钟)上就碰到过,而且涉及的数据 app 根本没用到。下面说说这条消息是什么意思、为什么会触发,以及怎么避免。
ITMS-90683 错误是什么意思?
完整消息标题是“ITMS-90683: Missing purpose string in Info.plist”。它表示你 app 的代码引用了某个涉及敏感数据的 API(照片、相机、麦克风、位置、通讯录),而 Info.plist 里没有对应的说明键。消息会写出这个键的名字,比如 NSPhotoLibraryUsageDescription。
这句说明叫做“purpose string”(用途说明)。它就是 iOS 在权限请求弹窗里显示的文字。Apple 在关于访问受保护资源的文档里写得很清楚:如果 app 的代码访问这些资源却没有 purpose string,App Review 会拒绝。
这不是审核员拒的。这项检查是自动的,在构建交付时、进入审核之前就会触发,和隐私清单的 ITMS-91053 一样。这个构建会被丢弃,你得重新上传一个。
为什么 app 没用这项数据,Apple 还是拒了
这是最让人意外的地方。**Apple 分析的是构建里包含的代码,而不是 app 实际做了什么。**只要你打包进去的某个库引用了相册,这个键就是必需的,哪怕没有任何界面会请求访问照片。Apple 的消息里自己也说明了:外部库或 SDK 可能会引用这些 API,purpose string 依然是必填的。
我的情况发生在 2026 年 9 月 26 日。整理 Solys 的配置时,我删掉了 NSPhotoLibraryUsageDescription 这个键,因为 app 完全不碰照片。结果下一个构建就被 ITMS-90683 拒了。原因是:app 用到的两个 Expo 库 expo-image 和 expo-file-system 里有引用相册的代码。之前的构建能通过,只是因为那个键还在。
教训:说明键不能因为“用不到”就删。只有当构建里再也没有任何库引用这个 API 时,才能删。
最常见的键
NSPhotoLibraryUsageDescription:读取或写入照片。NSPhotoLibraryAddUsageDescription:只添加照片,不读取。NSCameraUsageDescription:相机。NSMicrophoneUsageDescription:麦克风。NSLocationWhenInUseUsageDescription:使用期间的位置。NSContactsUsageDescription:通讯录。NSUserTrackingUsageDescription:广告追踪(App Tracking Transparency)。
Apple 的文档对每个键都有说明,比如 NSPhotoLibraryUsageDescription 的文档:只要 app 使用了读取或写入相册的 API,就必须提供它。
在 Expo app 中修复 ITMS-90683
- **记下 Apple 邮件里提到的键。**消息里会给出它的准确名称。
- 把它加到你的配置里,放在
ios.infoPlist下,参照 Expo 关于权限的文档:
{
"expo": {
"ios": {
"infoPlist": {
"NSPhotoLibraryUsageDescription": "Solys 不会访问你的照片。此权限永远不会被请求。"
}
}
}
}
- **重新构建。**Expo 明确说明:Info.plist 的修改无法通过远程更新下发,需要新的二进制文件。
- 把构建重新上传给 Apple,然后在你的版本里选中它。
如果你的 app 做了多语言,有个坑:语言文件只是翻译某个键,并不会声明它。这个键必须先存在于 ios.infoPlist(或相关插件的配置)里。否则 app 可能在第一次调用时崩溃。
如果 app 不用这项数据,该写什么?
Apple 要求说明准确、有用、具体。如果你的 app 真的用到了这项数据,就用一句话说清楚用途:“app 使用相机扫描你车票上的条形码。”
如果这个键只是因为某个库才需要,Apple 给了两种办法:写上说明,或者删掉访问该数据的代码。当代码来自某个库时,你没法简单地删掉它。所以在 Solys 上我写了实话:“Solys 不会访问你的照片。此权限永远不会被请求。”这是个务实的选择:下一个构建在交付时通过了,但我不能保证 Apple 永远接受这句话。
上传前找出缺失的键
在项目根目录运行下面这条命令,会列出 iOS 代码中引用了最受关注的那些 API 的库文件:
grep -rlE "PHPhotoLibrary|AVCaptureDevice|CLLocationManager|CNContactStore|EKEventStore|ATTrackingManager" \
node_modules/*/ios node_modules/@*/*/ios
每个名字对应一类数据:PHPhotoLibrary 是照片,AVCaptureDevice 是相机和麦克风,CLLocationManager 是位置,CNContactStore 是通讯录,EKEventStore 是日历,ATTrackingManager 是追踪。每出现一个结果,就检查你的配置里有没有对应的说明键。
这张网能兜住我遇到过的情况。但它代替不了仔细读 Apple 的邮件,邮件才是唯一可靠的清单,和 ITMS-90338 的非公开 API 一样。自从那次被拒,我每次构建前都会做这项检查:只要几秒钟,而一次 ITMS-90683 拒绝要浪费一个构建,外加重新构建的时间。
顺利上传你的构建
ITMS-90683 只要看懂了就能很快修好,针对 Xcode 版本的 ITMS-90725 也一样。之后来自审核员的拒绝就需要多花些心思了:处理流程见 app 被 Apple 拒绝页面,最常见的原因见 Apple 为什么拒绝 app。
要在上传前检查你的材料,Apple Review Kit 汇集了我的检查清单和会审阅你项目的 Claude Code skills。如果上传卡住了,想找个人帮你看看,和我预约一小时:我们通过视频通话,在你的屏幕上一起过你的项目。如果你正在准备第一次发布,做一次免费诊断:它会帮你理清步骤顺序,并把我的 Apple 防拒清单发给你。
常见问题
ITMS-90683 算是 App Review 拒绝吗?
不算人工审核员的拒绝。这是构建交付时、进入审核之前的自动检查,和图标相关的 ITMS-90717 一样。没人打开过你的 app。构建被丢弃了:你需要修改 Info.plist,然后上传一个新的。
为什么我的 app 没用某项数据,Apple 还要求对应的键?
因为 Apple 分析的是构建中的代码,而不是 app 的行为。只要打包进去的某个库引用了相册或相机,就必须提供说明键,哪怕没有任何界面会请求这项权限。
能用远程更新修复 ITMS-90683 吗?
不能。缺失的键在 Info.plist 里,而它是二进制文件的一部分。远程更新改不了这个文件:你必须重新构建,再上传给 Apple。
在 Expo 项目里,NSPhotoLibraryUsageDescription 加在哪里?
加在 app 配置的 ios.infoPlist 下,配上一句描述用途的话。有些库的插件也提供专门的设置,可能还会加入其他键,比如后台模式。无论哪种方式,这个键都必须存在于基础配置中,而不只是在翻译文件里。
没用到的说明键要删掉吗?
只有在构建里再也没有任何库引用相关 API 时才删。否则下次上传会被 ITMS-90683 拒绝。删除某个键之前,先在依赖项的 iOS 代码里搜一下这个 API 的名字。