Google 将 SDK iOS 映射到用户启动时的当前位置 Swift SwiftUI
Google Maps iOS SDK to user's current location on launch Swift SwiftUI
我正在尝试模仿 Google 地图的某些功能,在启动应用程序时,如果已授予所需的权限,相机将移动到用户的当前位置。
我已经使用自定义当前位置按钮实现了此功能,该按钮可以很好地将相机带到用户当前位置,但无法在启动时模仿它。地图在位置管理器之后初始化,但是,调用 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
}
}
}
在更新位置之前创建加载视图。然后一旦更新禁用加载视图并显示地图,它将在地图视图出现时开始相机移动。
我正在尝试模仿 Google 地图的某些功能,在启动应用程序时,如果已授予所需的权限,相机将移动到用户的当前位置。
我已经使用自定义当前位置按钮实现了此功能,该按钮可以很好地将相机带到用户当前位置,但无法在启动时模仿它。地图在位置管理器之后初始化,但是,调用 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
}
}
}
在更新位置之前创建加载视图。然后一旦更新禁用加载视图并显示地图,它将在地图视图出现时开始相机移动。