【发布时间】:2022-01-22 10:06:43
【问题描述】:
我正在尝试模仿谷歌地图的一些功能,在启动应用程序时,如果已授予所需的权限,相机会移动到用户的当前位置。
我已经使用自定义当前位置按钮实现了这一点,该按钮可以很好地将相机带到用户当前位置,但在启动时无法模仿。地图在位置管理器之后初始化,但是调用 didUpdateLocations 时会有延迟。这意味着它发生在地图完成初始化之后,因此 initialiseMapCamera() 默认为坐标 0,0。如果没有正确的烫发,地图相机默认为 1,1,正如预期的那样。
我确信有一种我没有想到的明显方法可以解决这个问题;非常感谢任何帮助。谢谢!
LocationManager - 首先实例化
class LocationManager: NSObject, ObservableObject {
private let locationManager = CLLocationManager()
@Published var authorizationStatus: CLAuthorizationStatus = .notDetermined {
willSet { objectWillChange.send() }
}
@Published var location: CLLocation? {
willSet { objectWillChange.send() }
}
var latitude: CLLocationDegrees {
return location?.coordinate.latitude ?? 0
}
var longitude: CLLocationDegrees {
return location?.coordinate.longitude ?? 0
}
override init() {
super.init()
locationManager.delegate = self
switch authorizationStatus {
case .authorizedAlways, .authorizedWhenInUse:
configureLocationSettings()
case .notDetermined, .restricted, .denied: break
@unknown default: fatalError()
}
}
func configureLocationSettings() {
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
func requestLocationPermissions() {
locationManager.requestWhenInUseAuthorization()
}
}
extension LocationManager: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last else { return }
self.location = location
}
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
self.authorizationStatus = manager.authorizationStatus
switch authorizationStatus {
case .authorizedAlways, .authorizedWhenInUse:
configureLocationSettings()
case .notDetermined, .restricted, .denied: return
@unknown default:
fatalError()
}
}
}
MapViewBridge - 之后实例化
struct MapViewControllerBridge: UIViewControllerRepresentable {
@EnvironmentObject var locationManager: LocationManager
@EnvironmentObject var mapViewModel: mapViewModel
func makeUIViewController(context: Context) -> MapViewController {
let uiViewController = MapViewController()
initialiseMapCamera(mapView: uiViewController.mapView)
return uiViewController
}
func updateUIViewController(_ uiViewController: MapViewController, context: Context) {
cameraToLocationButton(mapView: uiViewController.mapView)
}
private func initialiseMapCamera(mapView: GMSMapView) {
var cameraLocation: CLLocationCoordinate2D
switch locationManager.authorizationStatus {
case .authorizedAlways, .authorizedWhenInUse:
cameraLocation = CLLocationCoordinate2D(
latitude: locationManager.latitude,
longitude: locationManager.longitude)
case .notDetermined, .restricted, .denied:
cameraLocation = CLLocationCoordinate2D(latitude: 1.0, longitude: 1.0)
@unknown default:
fatalError()
}
mapView.camera = GMSCameraPosition.camera(withTarget: cameraLocation, zoom: defaultZoomLevel)
}
private func animateCameraToCurrentLocation(mapView: GMSMapView) {
let currentLocation = CLLocationCoordinate2D(
latitude: locationManager.latitude,
longitude: locationManager.longitude)
mapView.animate(with: GMSCameraUpdate.setTarget(currentLocation))
mapView.animate(toZoom: defaultZoomLevel)
}
private func cameraToLocationButton(mapView: GMSMapView) {
guard mapViewModel.cameraToLocation else {
return
}
switch locationManager.authorizationStatus {
case .authorizedWhenInUse, .authorizedAlways:
animateCameraToCurrentLocation(mapView: mapView)
case .notDetermined:
locationManager.requestLocationPermissions()
case .restricted, .denied:
DispatchQueue.main.async {
mapViewModel.showLocationSettingsAlert = true
}
@unknown default:
fatalError()
}
DispatchQueue.main.async {
mapViewModel.cameraToLocation = false
}
}
}
【问题讨论】:
-
在第一次调用
didUpdateLocations之前,您无法知道用户的实际位置。您可以做的是在获取位置时将其存储在UserDefaults中。这样下次启动时,您可以移动到以前的位置,这可能比默认位置更接近它们现在的位置
标签: ios swift swiftui cllocationmanager google-maps-sdk-ios