Swift iOS中Google Maps的CLLocationManager didUpdateLocations不更新相机问题
解决Google Map跟随用户位置移动的问题
核心问题分析
- GMSMapView为局部变量:你在
viewDidLoad中创建的navView是局部变量,后续无法在位置更新方法中引用,导致无法修改地图相机位置。 - 位置更新方法签名错误:你写的
didUpdateLocations是旧Objective-C兼容语法,Swift 5.7.2下不会被系统触发,必须使用符合Swift规范的签名。
修正步骤及完整代码
1. 将GMSMapView改为类属性
在ViewController类中声明navView属性,确保整个类可访问:
import UIKit import GoogleMaps import CoreLocation class ViewController: UIViewController, CLLocationManagerDelegate { var manager: CLLocationManager? // 声明为类属性,方便后续更新地图 var navView: GMSMapView! override func viewDidLoad() { super.viewDidLoad() manager = CLLocationManager() manager?.delegate = self manager?.desiredAccuracy = kCLLocationAccuracyBest // 根据场景选择授权类型,前台定位用WhenInUse更合理 manager?.requestWhenInUseAuthorization() manager?.startUpdatingLocation() let viewBounds = self.view.bounds // 初始用默认坐标,后续由位置更新回调修正 let defaultCoordinate = CLLocationCoordinate2D(latitude: 51.0447, longitude: -114.0719) let camera = GMSCameraPosition.camera(withTarget: defaultCoordinate, zoom: 15.0) navView = GMSMapView.map(withFrame: CGRect(x: 130, y: 10, width: viewBounds.maxX - 135 * 2, height: viewBounds.maxY - 20), camera: camera) navView.isMyLocationEnabled = true // 可选:开启内置的定位按钮,方便用户手动回到当前位置 navView.settings.myLocationButton = true self.view.addSubview(navView) } // 修正后的Swift标准位置更新回调 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { // 取数组最后一个元素作为最新位置 guard let latestLocation = locations.last else { return } let latestCoordinate = latestLocation.coordinate // 平滑移动地图相机到当前位置 let cameraUpdate = GMSCameraUpdate.setTarget(latestCoordinate, zoom: navView.camera.zoom) navView.moveCamera(cameraUpdate) // 可选:如果需要跟随用户移动方向,替换为下面代码 // let cameraUpdate = GMSCameraUpdate.setTarget(latestCoordinate, bearing: latestLocation.course, zoom: navView.camera.zoom) // navView.animate(with: cameraUpdate) } // 可选:处理定位权限变化,提升用户体验 func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { switch status { case .authorizedWhenInUse, .authorizedAlways: manager.startUpdatingLocation() case .denied, .restricted: // 提示用户开启权限 let alert = UIAlertController(title: "定位权限未开启", message: "请在设置中开启定位权限以使用地图功能", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) present(alert, animated: true) default: break } } }
2. 关键改动说明
- 类属性声明:把
navView改为类属性,解决后续无法引用的问题。 - 修正回调签名:使用Swift标准的
locationManager(_:didUpdateLocations:)方法,确保系统能正确触发位置更新回调。 - 平滑相机更新:用
GMSCameraUpdate.setTarget创建更新指令,通过moveCamera实现平滑移动,避免地图跳转生硬。 - 权限处理:添加
didChangeAuthorization方法,处理权限拒绝或受限的情况,引导用户开启权限。
额外注意事项
- Info.plist配置:必须在Info.plist中添加权限描述键,比如
NSLocationWhenInUseUsageDescription(前台定位)或NSLocationAlwaysAndWhenInUseUsageDescription(前后台定位),否则授权请求会被系统忽略。 - 初始位置优化:
viewDidLoad中直接获取manager?.location大概率为nil(定位尚未完成),因此用默认坐标初始化,后续靠回调修正。
内容的提问来源于stack exchange,提问作者jl118
相关产品推荐
相关产品推荐

