Expo请求后台定位权限报错NSLocation*UsageDescription键缺失
该报错的核心原因是iOS原生运行时未在Info.plist中读取到合规的定位权限声明,你贴出的app.json配置字段本身是完整的,问题基本出在以下几个环节,按顺序排查即可:
1. 排查调试环境兼容性
如果你当前使用官方Expo Go客户端调试后台定位功能,必然触发该报错。Expo Go是官方预编译的通用调试客户端,不会加载你项目中自定义的Info.plist配置,其内置的权限声明未覆盖后台定位场景,不支持后台定位能力调试。
调试后台定位必须使用自定义开发构建包,操作步骤:
- 执行
npx expo prebuild --clean清除旧原生构建缓存,将最新的app.json配置同步到原生工程 - 执行
npx expo run:ios在模拟器/真机安装自定义开发调试包,后续在这个自定义包内调试功能
2. 修正权限请求顺序
iOS系统强制要求定位权限按阶梯申请:禁止直接启动时就申请后台定位权限,必须先获取前台定位权限,再申请后台定位权限。你当前的代码直接调用requestBackgroundPermissionsAsync()不符合系统权限流程,部分版本的expo-location会将这类系统级拒绝误报为Info.plist缺key错误。
修正后的参考代码:
async function onClick() { // 第一步:申请前台定位权限 const foregroundRes = await Location.requestForegroundPermissionsAsync(); if (foregroundRes.status !== 'granted') { // 自行处理前台权限被拒绝的分支逻辑 return; } // 第二步:前台权限通过后,再申请后台定位权限 const backgroundRes = await Location.requestBackgroundPermissionsAsync(); if (backgroundRes.status !== 'granted') { // 自行处理后台权限被拒绝的分支逻辑 return; } // 权限全部校验通过后再执行业务逻辑 let location = await Location.getLastKnownPositionAsync(); let dist = 0; setInterval(async () => { const res = await getLocation(location!, dist); dist = res.dist; location = res.location; }, 5000); }
3. 校验配置同步有效性
构建完自定义开发包后,直接打开原生工程目录下的ios/<你的项目名>/Info.plist文件,确认你配置的NSLocationAlwaysAndWhenInUseUsageDescription、NSLocationWhenInUseUsageDescription等字段确实已同步到文件中。如果发现字段缺失,直接删除整个ios目录后重新执行prebuild命令即可,不要使用旧的缓存构建。
4. 版本兼容修复
如果你的项目最低支持版本为iOS 16及以上,建议将expo-location升级到15.0及以上版本。15.0以下的expo-location对iOS 16调整后的权限校验逻辑适配存在bug,会出现配置完整依然误报缺key的问题。
内容的提问来源于stack exchange,提问作者Jakobi

