Xcode中Background Mode配置失效无法开启位置更新后台模式怎么办
iOS 后台位置更新(Background Mode Location Updates)配置失效排查清单
按踩坑概率从高到低排,挨个核对基本能覆盖99%的配置问题:
- 别只在Signing & Capabilities里勾Location updates,Info.plist权限声明缺一个都不行:
- 仅前台用位置需要加
NSLocationWhenInUseUsageDescription,值写清楚你拿位置的具体用途,别写空字符串,不然系统会直接拒审,运行时也拿不到权限 - 要后台持续拿位置必须加
NSLocationAlwaysAndWhenInUseUsageDescription,如果还要兼容iOS10及更早版本,额外补NSLocationAlwaysUsageDescription - 注意:iOS14之后用户可以给模糊位置权限,如果你的业务需要精确位置,还要在申请权限的时候主动要求
fullAccuracy权限,不然拿到的位置偏差几公里,看起来就像更新失效
- 仅前台用位置需要加
- 代码里的CLLocationManager配置漏项是最高发的原因:
- 只调用
requestWhenInUseAuthorization拿不到后台位置权限,必须调用requestAlwaysAuthorization申请「始终允许」权限 - 必须手动把
CLLocationManager实例的allowsBackgroundLocationUpdates属性设为true,这个属性默认是false——哪怕你Capabilities里勾了后台模式,代码里没开这个开关,App切后台后最多10秒就会被系统挂起,位置回调直接断,系统还会打一条明确的崩溃日志提示你漏了这个配置 - 把
pausesLocationUpdatesAutomatically设为false,这个属性默认是true,系统判定设备长时间静止的时候会自动停掉位置更新,表现就是后台跑个十几分钟就没位置回调了 - 做轨迹记录、导航类功能的话,把
activityType设成对应的.fitness/.automotiveNavigation/.otherNavigation,别用默认的.other,系统给这类场景的后台运行优先级更高,不会随便杀进程
- 只调用
- 检查Capability是不是加错了地方:
- 多Target开发的时候很容易把Background Modes加到测试Target、Widget扩展Target上,主Target根本没生效。直接去主Target的Info.plist里看
UIBackgroundModes数组里有没有location这个值,没有就是没加对 - 用CocoaPods的话,检查Podfile里的
post_install钩子,很多第三方SDK的配置脚本会乱改主Target的UIBackgroundModes配置,把你手动加的location项冲掉
- 多Target开发的时候很容易把Background Modes加到测试Target、Widget扩展Target上,主Target根本没生效。直接去主Target的Info.plist里看
- 核对实际拿到的权限状态,别想当然:
- 弹了权限申请不代表用户给了「始终允许」,iOS13之后系统会先给用户三个选项:
仅使用App期间、允许一次、不允许,「始终允许」不会在第一次弹窗里出现,需要用户用几次之后系统才会弹二次确认,或者手动去设置里改。要在locationManagerDidChangeAuthorization回调里实时判断authorizationStatus,如果状态是.authorizedWhenInUse,哪怕你勾了后台模式,切后台之后也拿不到持续位置
- 弹了权限申请不代表用户给了「始终允许」,iOS13之后系统会先给用户三个选项:
- 别用错误的测试方式测出来假失效:
- 别挂着Xcode调试测后台行为,Xcode附加调试的时候会给App开特殊的后台存活权限,测出来的结果完全不准。正确测法是断了Xcode连接,手动在真机上启动App,切后台之后看位置回调是否正常
- 别用模拟器测后台位置,模拟器的后台权限调度逻辑和真机差很多,必须拿真机测。另外真机开低电量模式的时候,系统会主动降低后台位置更新频率,甚至暂停非导航类的位置更新,测的时候先把低电量模式关了
快速定位技巧:把真机连Xcode,看切后台时控制台的输出,如果看到类似
App must set allowsBackgroundLocationUpdates to YES to receive location updates in background的日志,直接对应改代码就行,不用瞎查配置。
- 特殊场景补查:
- 如果你设的
distanceFilter阈值太大,移动距离没到设定值的时候不会触发位置回调,看起来就像后台更新失效,测试的时候可以先把distanceFilter设成kCLDistanceFilterNone排除这个问题 - 如果你用的是重大位置变更(Significant Location Change)、地理围栏(Region Monitoring)这类低功耗位置能力,不需要勾Location updates后台模式也能在后台唤醒,但是普通的连续定位必须勾,而且这两类能力在App被用户手动杀掉之后也能唤醒,普通连续定位做不到
- 如果App同时集成了多个拿位置的SDK,检查有没有其他SDK在后台把定位服务停掉的情况
- 如果你设的
内容的提问来源于stack exchange,提问作者pizzajuice
相关产品推荐
相关产品推荐

