如何将谷歌地图摄像头聚焦于用户';使用swiftUI视图启动时的当前位置
我正在尝试制作一个使用谷歌地图的应用程序,并在应用程序打开时关注用户的位置 现在,我已经初始化了地图,按下谷歌地图固有的“myLocation”按钮后,我可以聚焦到用户的位置,但地图的摄像头会一直聚焦到指定的位置,而不是用户的位置 我通过以下两个教程了解了我现在的处境: - - 在搜索Google和此处之后,似乎我需要利用CLLocationManager()获取用户的设备坐标,然后以某种方式使用它?我认为我关于CLLocationManager()的代码可能放在错误的文件中或使用不正确,但我没有收到任何错误 我的代码是这样工作的:SceneDelegate.swift将我的LandmarkList.swift设置为rootViewController。然后LandmarkList调用GoogMapView.swift来显示Google地图的实例 SceneDelegate.swift: 我想我在这里使用locationManager可能是错误的如何将谷歌地图摄像头聚焦于用户';使用swiftUI视图启动时的当前位置,swift,cllocationmanager,swiftui,google-maps-sdk-ios,xcode11,Swift,Cllocationmanager,Swiftui,Google Maps Sdk Ios,Xcode11,我正在尝试制作一个使用谷歌地图的应用程序,并在应用程序打开时关注用户的位置 现在,我已经初始化了地图,按下谷歌地图固有的“myLocation”按钮后,我可以聚焦到用户的位置,但地图的摄像头会一直聚焦到指定的位置,而不是用户的位置 我通过以下两个教程了解了我现在的处境: - - 在搜索Google和此处之后,似乎我需要利用CLLocationManager()获取用户的设备坐标,然后以某种方式使用它?我认为我关于CLLocationManager()的代码可能放在错误的文件中或使用不正确,但
import UIKit
import SwiftUI
import GoogleMaps
import GooglePlaces
import CoreLocation
class SceneDelegate: UIResponder, UIWindowSceneDelegate, CLLocationManagerDelegate {
var window: UIWindow?
private let locationManager = CLLocationManager()
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
// Use a UIHostingController as window root view controller
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: LandmarkList())
self.window = window
window.makeKeyAndVisible()
}
locationManager.requestAlwaysAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
}
}
}
LandmarkList.swift:
import SwiftUI
struct LandmarkList: View {
@State private var searchText = ""
@State private var locationText = ""
var body: some View {
ZStack(alignment: Alignment.top) {
GoogMapView()
.frame(height: 750)
SlideOverCard {
VStack(alignment: .leading) {
List(landmarkData) { landmark in
NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
LandmarkRow(landmark: landmark)
}
}
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: Alignment.topLeading)
}
}
}
}
GoogMapView.swift:
注意:下面的打印语句仅返回“用户位置未知”
import SwiftUI
import UIKit
import GoogleMaps
import GooglePlaces
import CoreLocation
struct GoogMapView : UIViewRepresentable {
let marker : GMSMarker = GMSMarker()
//Creates a `UIView` instance to be presented.
func makeUIView(context: 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")
}
return mapView
}
// Updates the presented `UIView` (and coordinator) to the latestconfiguration.
func updateUIView(_ mapView: GMSMapView, context: 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
}
}
同样,我认为我在SceneDelegate.swift中关于locationManager的代码会使GoogleMaps摄像头的实例在启动时关注用户的位置,但事实并非如此
有人知道我做错了什么吗?您可以通过“假装”您的视图是ViewController来实现这一点。尝试将谷歌地图视图
设置为代理。然后将初始化代码放入makeUIView
中,然后遵守协议:
struct GoogMapView : CLLocationManagerDelegate {
private let locationManager = CLLocationManager()
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
guard status == .authorizedWhenInUse else {
return
}
locationManager.startUpdatingLocation()
mapView.isMyLocationEnabled = true
mapView.settings.myLocationButton = true
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.first else {
return
}
mapView.camera = GMSCameraPosition(target: location.coordinate, zoom: 15, bearing: 0, viewingAngle: 0)
locationManager.stopUpdatingLocation()
}
}
以上摘自。使用此处的注释和其他有关StackOverflow的注释,我提出了以下解决方案:
//
// GoogMapView.swift
// Landmarks
//
// Created by Zahr Lyttle on 10/14/19.
// Copyright © 2019 Apple. All rights reserved.
//
import SwiftUI
import UIKit
import GoogleMaps
import GooglePlaces
import CoreLocation
import Foundation
struct GoogMapView: View {
var body: some View {
GoogMapControllerRepresentable()
}
}
class GoogMapController: UIViewController, CLLocationManagerDelegate {
var locationManager = CLLocationManager()
var mapView: GMSMapView!
let defaultLocation = CLLocation(latitude: 42.361145, longitude: -71.057083)
var zoomLevel: Float = 15.0
let marker : GMSMarker = GMSMarker()
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.distanceFilter = 50
locationManager.startUpdatingLocation()
locationManager.delegate = self
let camera = GMSCameraPosition.camera(withLatitude: defaultLocation.coordinate.latitude, longitude: defaultLocation.coordinate.longitude, zoom: zoomLevel)
mapView = GMSMapView.map(withFrame: view.bounds, camera: camera)
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
mapView.isMyLocationEnabled = true
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")
// }
marker.position = CLLocationCoordinate2D(latitude: 42.361145, longitude: -71.057083)
marker.title = "Boston"
marker.snippet = "USA"
marker.map = mapView
// Add the map to the view, hide it until we've got a location update.
view.addSubview(mapView)
// mapView.isHidden = true
}
// Handle incoming location events.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location: CLLocation = locations.last!
print("Location: \(location)")
let camera = GMSCameraPosition.camera(withLatitude: location.coordinate.latitude, longitude: location.coordinate.longitude, zoom: zoomLevel)
if mapView.isHidden {
mapView.isHidden = false
mapView.camera = camera
} else {
mapView.animate(to: camera)
}
}
// Handle authorization for the location manager.
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .restricted:
print("Location access was restricted.")
case .denied:
print("User denied access to location.")
// Display the map using the default location.
mapView.isHidden = false
case .notDetermined:
print("Location status not determined.")
case .authorizedAlways: fallthrough
case .authorizedWhenInUse:
print("Location status is OK.")
}
}
// Handle location manager errors.
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
locationManager.stopUpdatingLocation()
print("Error: \(error)")
}
}
struct GoogMapControllerRepresentable: UIViewControllerRepresentable {
func makeUIViewController(context: UIViewControllerRepresentableContext<GMControllerRepresentable>) -> GMController {
return GMController()
}
func updateUIViewController(_ uiViewController: GMController, context: UIViewControllerRepresentableContext<GMControllerRepresentable>) {
}
}
//
//斯威夫特
//地标
//
//扎尔·利特尔于19年10月14日创作。
//版权所有©2019苹果公司。版权所有。
//
导入快捷键
导入UIKit
导入谷歌地图
导入谷歌网站
导入核心定位
进口基金会
结构GoogMapView:视图{
var body:一些观点{
GoogMapControllerRepresentable()
}
}
类GoogMapController:UIViewController、CLLocationManagerDelegate{
var locationManager=CLLocationManager()
var地图视图:GMSMapView!
设defaultLocation=CLLocation(纬度:42.361145,经度:-71.057083)
var zoomLevel:Float=15.0
let marker:GMSMarker=GMSMarker()
重写func viewDidLoad(){
super.viewDidLoad()
locationManager=CLLocationManager()
locationManager.desiredAccuracy=KCallocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.distanceFilter=50
locationManager.startUpdatingLocation()
locationManager.delegate=self
让camera=GMSCameraPosition.camera(带纬度:defaultLocation.coordinate.latitude,经度:defaultLocation.coordinate.latitude,缩放:zoomLevel)
mapView=GMSMapView.map(带边框:view.bounds,相机:相机)
mapView.autoresizingMask=[.flexibleWidth、.flexibleHeight]
mapView.isMyLocationEnabled=true
mapView.setMinZoom(14,maxZoom:20)
mapView.settings.compassButton=true
mapView.isMyLocationEnabled=true
mapView.settings.myLocationButton=true
mapView.settings.ScrollPictures=true
mapView.settings.zoomGestures=true
mapView.settings.rotateGestures=true
mapView.settings.tiltsignities=true
mapView.ISINDORENABLED=false
//如果让mylocation=mapView.mylocation{
//打印(“用户位置:\(mylocation)”)
//}其他{
//打印(“用户位置未知”)
// }
marker.position=CLLocationCoordinate2D(纬度:42.361145,经度:-71.057083)
marker.title=“波士顿”
marker.snippet=“美国”
marker.map=mapView
//将地图添加到视图中,隐藏它,直到获得位置更新。
view.addSubview(地图视图)
//mapView.ishiden=true
}
//处理传入的位置事件。
func locationManager(manager:CLLocationManager,didUpdateLocations位置:[CLLocation]){
let location:CLLocation=locations.last!
打印(“位置:\(位置)”)
让camera=GMSCameraPosition.camera(带纬度:位置.坐标.纬度,经度:位置.坐标.经度,缩放:缩放级别)
如果mapView.isHidden{
mapView.ishiden=false
mapView.camera=camera
}否则{
地图视图.动画(到:摄影机)
}
}
//处理位置管理器的授权。
func locationManager(\ manager:CLLocationManager,didChangeAuthorization状态:CLAuthorizationStatus){
开关状态{
案例.限制性:
打印(“位置访问被限制。”)
案件.驳回:
打印(“用户拒绝访问位置”)
//使用默认位置显示地图。
mapView.ishiden=false
案例。未确定:
打印(“位置状态未确定”)
案例.方法:失败
案例.授权使用:
打印(“位置状态正常”)
}
}
//处理位置管理器错误。
func locationManager(manager:CLLocationManager,didFailWithError:error){
locationManager.StopUpdatengLocation()
打印(“错误:\(错误)”)
}
}
结构GoogMapControllerRepresentable:UIViewControllerRepresentable{
func makeUIViewController(上下文:UIViewControllerRepresentableContext)->GMController{
返回GMController()
}
func updateUIViewController(uViewController:GMController,上下文:UIViewControllerRepresentableContext){
}
}
我终于能够想出如何立即关注“我的位置”,而不需要用户的输入。这里有更多的细节…希望对你有所帮助
updateUIView
- 你
import SwiftUI import GoogleMaps import Combine struct HomeView: UIViewRepresentable { // Listen to changes on the locationManager @ObservedObject var locationManager = LocationManager() func makeUIView(context: Self.Context) -> GMSMapView { // Just default the camera to anywhere (this will be overwritten as soon as myLocation is grabbed let camera = GMSCameraPosition.camera(withLatitude: 0, longitude: 0, 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 return mapView } func updateUIView(_ mapView: GMSMapView, context: Self.Context) { // When the locationManager publishes updates, respond to them if let myLocation = locationManager.lastKnownLocation { mapView.animate(toLocation: myLocation.coordinate) print("User's location: \(myLocation)") } } }
class LocationManager: NSObject, CLLocationManagerDelegate, ObservableObject { // Publish the user's location so subscribers can react to updates @Published var lastKnownLocation: CLLocation? = nil private let manager = CLLocationManager() override init() { super.init() self.manager.delegate = self self.manager.startUpdatingLocation() } func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { if status == .authorizedWhenInUse { self.manager.startUpdatingLocation() } } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { // Notify listeners that the user has a new location self.lastKnownLocation = locations.last } }