如何使用 SwiftUI 和 GoogleMaps iOS SDK 关注用户位置

How to focus on user location using SwiftUI and GoogleMaps iOS SDK

我还是 Xcode 和 SwiftUI 的新手,所以如果这对某些人来说很简单,我深表歉意。本质上,我正在制作一个使用 GoogleMaps iOS SDK 的应用程序,我正在尝试弄清楚如何在启动时将地图的相机聚焦到用户的当前位置。

现在我的代码的工作方式是我有一个调用 GoogleMaps 视图的主视图和几个其他视图。地图初始化并且地图的相机聚焦在我定义的设置位置(波士顿),在特定位置(波士顿)放置一个图钉,它用蓝点显示我的当前位置,并且相机仅在myLocation 按钮被点击(Google 地图固有)。

调用我的 Google 地图视图的主视图在这里:


import SwiftUI

struct LandmarkList: View {

    @State private var searchText = ""
    @State private var locationText = ""

    var body: some View {

        NavigationView {

            GoogMapView()
                .frame(height: 750)
        }
        .edgesIgnoringSafeArea(.vertical)
        .navigationBarItems(leading:

        TextField("Current Location",text: self.$locationText)
        .textFieldStyle(RoundedBorderTextFieldStyle())
        .multilineTextAlignment(.leading)
        .frame(width: 375)
            )

        }

我的 Google 地图视图(我称之为 GoogMapView): 根据以下评论和教程更新:

import SwiftUI
//import MapKit
import UIKit
import GoogleMaps
import GooglePlaces


private let locationManager = CLLocationManager()

struct GoogMapView : UIViewRepresentable {

        let marker : GMSMarker = GMSMarker()

        //Creates a `UIView` instance to be presented.
        func makeUIView(context: Self.Context) -> GMSMapView {
            // Create a GMSCameraPosition
            let camera = GMSCameraPosition.camera(withLatitude: 42.361145, longitude: -71.057083, zoom: 16.0)
            let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
            mapView.setMinZoom(14, maxZoom: 20)
            mapView.settings.compassButton = true
            mapView.isMyLocationEnabled = true
            mapView.settings.myLocationButton = true
            mapView.settings.scrollGestures = true
            mapView.settings.zoomGestures = true
            mapView.settings.rotateGestures = true
            mapView.settings.tiltGestures = true
            mapView.isIndoorEnabled = false

            if let mylocation = mapView.myLocation {
              print("User's location: \(mylocation)")
            } else {
              print("User's location is unknown")
            }
            locationManager.delegate = self
            locationManager.requestWhenInUseAuthorization()

            return mapView
        }

//        Updates the presented `UIView` (and coordinator) to the latestconfiguration.
        func updateUIView(_ mapView: GMSMapView, context: Self.Context) {
            // Creates a marker in the center of the map.
            marker.position = CLLocationCoordinate2D(latitude: 42.361145, longitude: -71.057083)
            marker.title = "Boston"
            marker.snippet = "USA"
            marker.map = mapView
        }
}

我以为我可以抓取 mapView.myLocation 并使用它在启动时手动聚焦地图相机,但那没有用。您可以在上面的代码中看到我尝试打印出位置,但我得到的只是“用户的位置未知”。 此外,现在出现错误“无法将类型 'GoogMapView' 的值分配给类型 'CLLocationManagerDelegate?'”,其中我键入 'locationManager.delegate = self'.

有没有人知道 'proper' 在启动时让地图相机聚焦在用户当前位置的方法?

I thought i could grab mapView.myLocation and use that to manually focus the map camera on startup but that didnt work. You can see in the code above i try to print out the location but all i get back is 'User's location is unknown'

看起来 mylocation 不包含任何位置坐标。 mapView.myLocation 可能不是你想的那样,也许它保存的是用户的设备位置,而不是你传递给 GMSCameraPosition[= 的坐标23=]。根据文档

If My Location is enabled, reveals where the user location dot is being drawn.

所以这不是你传给相机的那个

Does anyone have an idea of the 'proper' way to have the map camera focus on a user's current location at startup?

您是否在某处创建了一个位置管理器并处理了位置权限?如果有,您可以在名为 didUpdateLocations 的函数中捕获用户的位置 - 启动时检索用户位置需要几秒钟左右的时间。获取位置后,您可以将相机平移到该位置。

  • 在另一个 class 中调用 locationManager.requestWhenInUseAuthorization()。不需要 locationManager.startUpdatingLocation
  • google 地图将接收您的位置。然后跟随你的位置。
  • 如果你想要enable/disable跟踪模式条件,使用mapView.tag属性。

struct GoogleMapView: UIViewRepresentable {
  @State var coordinator = Coordinator()

  func makeUIView(context _: Context) -> GMSMapView {
    let view = GMSMapView(frame: .zero)
    view.isMyLocationEnabled = true
    view.animate(toZoom: 18)
    view.addObserver(coordinator, forKeyPath: "myLocation", options: .new, context: nil)
    return view
  }

  func updateUIView(_ uiView: GMSMapView, context _: UIViewRepresentableContext<GoogleMapView>) {}

  func makeCoordinator() -> GoogleMapView.Coordinator {
    return coordinator
  }

  static func dismantleUIView(_ uiView: GMSMapView, coordinator: GoogleMapView.Coordinator) {
    uiView.removeObserver(coordinator, forKeyPath: "myLocation")
  }

  final class Coordinator: NSObject {
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
      if let location = change?[.newKey] as? CLLocation, let mapView = object as? GMSMapView {
        mapView.animate(toLocation: location.coordinate)
      }
    }
  }
}