iOS12.3+ Objective-C 定位:废弃didUpdateToLocation方法替换及坐标不更新解决
核心问题根因
- 你遇到的编译警告,源于使用了从iOS 6.0就被苹果标记为废弃的
didUpdateToLocation:fromLocation:代理方法。你适配的iOS12.3系统已经完全不会回调这个方法,哪怕你把代码逻辑写得完全正确,这个方法也永远不会被系统触发,所以点按钮之后没有任何回调、标签不更新是必然结果。 - 现有代码还存在两个会导致定位完全失效的硬伤:
- 没有在Info.plist中声明定位权限的用途描述。按照iOS的权限规则,缺少对应描述时,系统会静默拦截所有定位请求,既不会弹出授权框,也不会触发定位失败的回调流程,从外部看就是点按钮完全没反应。
- 没有主动触发定位权限的申请流程,也没有做权限状态判断,在未获得授权的状态下直接调用
startUpdatingLocation,系统会直接静默拒绝请求。
兼容iOS12.3的替代方案
苹果从iOS 5.0开始就推出了完全向下兼容的新代理方法locationManager:didUpdateLocations:,这个方法会把连续的定位结果通过数组传回来,适配从iOS12.3到最新系统的所有版本,没有任何废弃风险。
使用这个方法替换原废弃方法的同时,补上权限申请、无效位置过滤的逻辑,就能保证正常拿到定位数据。
可直接落地的代码调整
第一步:配置Info.plist必填项
在项目的Info.plist文件中新增以下键值对,否则权限申请流程无法触发:
- 新增
Privacy - Location When In Use Usage Description键,对应的值填写定位用途说明,比如“需要获取当前位置以展示经纬度坐标信息”
第二步:调整按钮点击的权限判断逻辑
替换原getCurrentLocation: 方法的代码,补充权限状态判断和申请流程:
- (IBAction)getCurrentLocation:(UIButton *)sender { locationManager.delegate = self; locationManager.desiredAccuracy = kCLLocationAccuracyBest; // 获取当前App的定位权限状态 CLAuthorizationStatus authStatus = [CLLocationManager authorizationStatus]; if (authStatus == kCLAuthorizationStatusNotDetermined) { // 用户尚未做过授权选择,主动弹出授权申请框 [locationManager requestWhenInUseAuthorization]; } else if (authStatus == kCLAuthorizationStatusAuthorizedWhenInUse || authStatus == kCLAuthorizationStatusAuthorizedAlways) { // 已经获得授权,直接启动定位 [locationManager startUpdatingLocation]; } else { // 权限被永久拒绝,打印日志引导用户去系统设置开启权限 NSLog(@"定位权限已被拒绝,请前往系统设置中为App开启定位权限"); } }
第三步:替换废弃的定位回调方法
直接删除原来的didUpdateToLocation:fromLocation: 方法,替换为新的兼容代理方法,同时补充无效位置过滤逻辑,避免拿到缓存的旧定位数据:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations { // 取数组中最新的定位结果 CLLocation *currentLocation = locations.lastObject; // 过滤超过5秒的缓存旧位置 NSTimeInterval locationAge = -[currentLocation.timestamp timeIntervalSinceNow]; if (locationAge > 5.0) { return; } // 过滤精度为负的无效定位 if (currentLocation.horizontalAccuracy < 0) { return; } NSLog(@"获取到有效定位:%@", currentLocation); // 更新经纬度标签 if (currentLocation != nil) { longitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude]; lattitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude]; } // 拿到有效定位后立即停止更新,减少设备耗电 [locationManager stopUpdatingLocation]; NSLog(@"开始反向解析地理位置信息"); [geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) { NSLog(@"地址解析结果:%@,错误信息:%@", placemarks, error); if (error == nil && placemarks.count > 0) { self->placemark = placemarks.lastObject; self->addressLabel.text = [NSString stringWithFormat:@"%@ %@\n%@ %@\n%@\n%@", self->placemark.subThoroughfare, self->placemark.thoroughfare, self->placemark.postalCode, self->placemark.locality, self->placemark.administrativeArea, self->placemark.country]; } else { NSLog(@"地址解析失败:%@", error.debugDescription); } }]; }
真机测试注意事项
- 首次点击按钮时,注意观察系统是否弹出定位授权框,如果没有弹出,优先检查Info.plist里的权限描述键名是否拼写正确、值是否为空
- 如果已经授权但长时间拿不到定位,尽量在靠近窗边的位置测试,iPhone5s没有辅助的高精度定位芯片,室内GPS信号弱时首次定位会需要更长时间
- 优先在真机上测试逻辑,不要用模拟器的定位功能代替真机验证,避免出现兼容性误判
参考资源方向
- 苹果官方CoreLocation框架开发指南,内容覆盖了从iOS12开始的全版本适配规则、权限处理逻辑
- 开源项目参考可以直接在GitHub站内搜索带“CoreLocation + Objective-C + iOS12适配”标签的项目,优先选择代码中没有使用废弃API、最近有维护更新的Demo学习。
内容的提问来源于stack exchange,提问作者THEJAS
相关产品推荐
相关产品推荐

