Как сфокусироваться на местоположении пользователя с помощью SwiftUI и GoogleMaps iOS SDK

Я все еще новичок в Xcode и SwiftUI, поэтому приношу свои извинения, если для некоторых это просто. По сути, я создаю приложение, которое использует SDK GoogleMaps для iOS, и я пытаюсь понять, как при запуске сфокусировать камеру карты на текущее местоположение пользователя.

Прямо сейчас мой код работает так: у меня есть главное представление, которое вызывает представление GoogleMaps и несколько других представлений. Карта инициализируется, и камера карты фокусируется на заданном мной месте (Бостон), ставит булавку в определенном месте (Бостон), мое текущее местоположение отображается синей точкой, а камера фокусируется на моем текущем местоположении ТОЛЬКО ПОСЛЕ Нажата кнопка myLocation (которая присуща Google Maps).

Мое основное представление, вызывающее мои карты 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».

Есть ли у кого-нибудь представление о «правильном» способе фокусировки камеры карты на текущем местоположении пользователя при запуске?


person zlyt    schedule 09.10.2019    source источник
comment
Я думаю, вам стоит подробно ознакомиться с SDK Google Maps. Это не похоже на проблему SwiftUI   -  person Hamoonist    schedule 10.10.2019
comment
Да, я не думаю, что это проблема SwiftUI, но больше о том, «как я могу сделать это правильно?». Я сослался на документацию Google здесь (developers.google.com/maps/documentation/ios- sdk / views), но это не помогло мне сосредоточиться на местоположении пользователя при запуске ... что, как мне кажется, должно быть построено так же, как кнопка myLocation и другие настройки?   -  person zlyt    schedule 10.10.2019


Ответы (2)


Я думал, что могу взять mapView.myLocation и использовать его для ручной фокусировки камеры карты при запуске, но это не сработало. В приведенном выше коде вы можете видеть, что я пытаюсь распечатать местоположение, но все, что я получаю, это «Местоположение пользователя неизвестно».

Похоже, mylocation не содержит координат местоположения. mapView.myLocation может быть не тем, что вы думаете, возможно, он содержит местоположение устройства пользователя, а не координату, которую вы передаете в GMSCameraPosition. Согласно документации

Если "Мое местоположение" включено, показывает, где отображается точка местоположения пользователя.

Так что это не тот, который вы передаете в камеру

Есть ли у кого-нибудь представление о «правильном» способе фокусировки камеры карты на текущем местоположении пользователя при запуске?

Вы где-то создали LocationManager и разобрались с разрешениями на местоположение? Если да, то вы можете определить местоположение пользователя с помощью функции под названием didUpdateLocations - получение местоположения пользователя при запуске занимает пару секунд или около того. Как только вы определите местоположение, вы можете повернуть камеру к нему.

person Mark Villar    schedule 10.10.2019
comment
Я не создавал locationManager. Я использовал info.plist, чтобы разрешить приложению использовать местоположение моего устройства, но я попытаюсь заставить locationManager работать, как вы сказали, чтобы камера фокусировалась на местоположении при запуске. Вы могли бы подумать, что Google сделает это так же просто, как установит для свойства значение true, например кнопку myLocation / синюю точку, хотя - person zlyt; 10.10.2019
comment
Есть отличный учебник от Рей Вендерлиха, который делает большую часть, если не все, из того, что вы пытаетесь сделать с помощью SDK Google Maps: raywenderlich.com/ - person Mark Villar; 10.10.2019
comment
Учебник был очень хорошим, но я стараюсь держаться подальше от раскадровок. Похоже, что код, который у него есть для locationManager, должен находиться в UIViewController, а не в UIViewRepresentable, как я использую. Есть какие-нибудь мысли о том, как реализовать locationManager.delegate = self в функции makeUIView? - person zlyt; 11.10.2019
comment
Вы можете обернуть весь ViewController, то есть MapView, который включает locationManager, используя UIViewControllerRepresentable, а затем использовать его как представление внутри SwiftUI. У меня есть еще одна ссылка, которая, надеюсь, поможет как-то: sarunw.com/posts/uikit-in- swiftui, в нем объясняется, как обернуть любой компонент UIKit для SwiftUI. - person Mark Villar; 13.10.2019

  • вызов locationManager.requestWhenInUseAuthorization() в другом классе. не нужно locationManager.startUpdatingLocation
  • карта Google получит ваше местоположение. затем следите за своим местоположением.
  • если вы хотите включить / выключить условие режима отслеживания, используйте свойство 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)
      }
    }
  }
}
person Changhoon    schedule 30.03.2020