【问题标题】:Google Maps iOS SDK to user's current location on launch Swift SwiftUIGoogle Maps iOS SDK 在启动 Swift SwiftUI 时到用户的当前位置
【发布时间】: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


【解决方案1】:

创建加载视图,直到位置更新。然后一旦更新禁用加载视图并显示地图,它将在地图视图出现时开始相机移动。

【讨论】:

    猜你喜欢
    • 2014-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多