【问题标题】:Current location in not working in Google Map当前位置在谷歌地图中不起作用
【发布时间】:2017-02-24 13:51:51
【问题描述】:

我已经在 swift 3 中集成了谷歌地图,当地图屏幕出现而不是当前位置时,我在 .plist 文件中添加了两个键,并设置了 CLLocationManager 委托和 requestAlwaysAuthorization

class MapViewController: UIViewController, CLLocationManagerDelegate, UITextFieldDelegate {

    @IBOutlet var mapView: GMSMapView!
    var marker: GMSMarker?


    override func viewDidLoad() {
         super.viewDidLoad()
         self.title = "MapVC"
         self.doSetupUI()
         self.searchLocation()
   }

   override func viewWillAppear(_ animated: Bool) {
         let locationManager : CLLocationManager = CLLocationManager()
         locationManager.delegate = self
         locationManager.requestAlwaysAuthorization()
   }



func doGoogleMapSetup(lat : Double , lng : Double) {
    let camera = GMSCameraPosition.camera(withLatitude: lat, longitude:lng, zoom:16)
    let mapView = GMSMapView.map(withFrame: .zero, camera:camera)
    mapView.isMyLocationEnabled = true

    let marker = GMSMarker()
    marker.position = CLLocationCoordinate2D(latitude: lat, longitude: lng)
    marker.snippet = ""
    marker.appearAnimation = kGMSMarkerAnimationPop
    marker.map = mapView

    let arrPoints : NSMutableArray = NSMutableArray()
    arrPoints.add(UserDefaults.standard.object(forKey: "addressPoints"))

    for i in 0..<arrPoints.count {
        let path : String = (arrPoints.object(at: i)as! NSMutableArray).object(at: 0) as! String
        let route : GMSPath = GMSPath.init(fromEncodedPath: path)!
        let polyLine : GMSPolyline = GMSPolyline.init(path: route)
        polyLine.strokeWidth = 2.0
        polyLine.strokeColor = UIColor.red
        polyLine.map = mapView
    }
}

【问题讨论】:

  • 请出示您的代码
  • 另外,“位置”是什么意思?您是在说地标,指示用户位置吗?您是否正在尝试获取地图的中心坐标?还是别的什么?
  • hiii,我正在尝试获取用户的当前位置
  • func locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation) { let latitude: Double = newLocation.coordinate.latitude let longitude: Double = newLocation.coordinate.longitude currentlat = latitude currentlong = 经度 }
  • @Dhanraj:您不应该需要地图来获取用户的位置。 locationManager.location 应该为您提供用户的地理坐标。

标签: ios swift google-maps swift3 cllocationmanager


【解决方案1】:

GoogleMaps 的情况下,我们不需要任何位置管理器来显示当前位置。我们只需要在 .plist 中添加一个或两个键。所以确保钥匙在那里。我使用了NSLocationWhenInUseUsageDescription 键。

<key>NSLocationWhenInUseUsageDescription</key>
    <string>Allow location</string>

还要确保您已调用 GMSServices provideAPIKey 方法并替换为您在 Google 开发者控制台中生成的 API_KEY。还应根据要求启用所有相关的 Google API。

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
       // Override point for customization after application launch.
       GMSServices.provideAPIKey("YOUR_API_KEY")
       return true
    }

因此,我假设您已在 Google 开发者控制台中正确完成所有设置和操作。

只需在您创建GoogleMap 的控制器中写入以下行,就可以显示位置允许/禁止提示并获得用户的许可。

mapView.isMyLocationEnabled = true

但是,这不会将您的地图动画化到您当前的位置。但是您可以手动拖动地图查看当前位置,您会在当前位置看到一个蓝点。

但现在我们还想在加载 ViewController 时动画到当前位置。现在需要CLLocationManager。因此,在其didUpdateLocation 委托中,我们可以获取当前位置,并且可以将图形动画到当前位置。

这是我的完整控制器。

import UIKit
import GoogleMaps

class ViewController: UIViewController,GMSMapViewDelegate,CLLocationManagerDelegate {
    @IBOutlet weak var mapView: GMSMapView!

    var locationManager = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()
        mapView.isMyLocationEnabled = true
        mapView.delegate = self

        //Location Manager code to fetch current location
        self.locationManager.delegate = self
        self.locationManager.startUpdatingLocation()
    }

    //Location Manager delegates
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

        let location = locations.last

        let camera = GMSCameraPosition.camera(withLatitude: (location?.coordinate.latitude)!, longitude:(location?.coordinate.longitude)!, zoom:14)
        mapView.animate(to: camera)

        //Finally stop updating location otherwise it will come again and again in this delegate
        self.locationManager.stopUpdatingLocation()

    }
}

另一种方法是不使用didUpdateLocation,不使用位置管理器只是使用GMSMapViewDelegate委托方法mapViewDidFinishTileRendering

func mapViewDidFinishTileRendering(_ mapView: GMSMapView) {
    let location = mapView.myLocation
    let camera = GMSCameraPosition.camera(withLatitude: (location?.coordinate.latitude)!, longitude:(location?.coordinate.longitude)!, zoom:14)
    mapView.animate(to: camera)
}

每次地图渲染完成时都会调用它。
但这有一个限制,每当您拖动/捏合/缩放地图时,它总是会将您带到当前位置,因为每次使用地图时渲染完成。所以,你可以在这里实现某种bool 变量逻辑。

您可以通过使用获取您的位置

let yourCurrentLocation = mapView.myLocation

确保在设备而不是模拟器上执行此操作。如果您使用的是模拟器,则必须选择一些自定义位置,然后才能看到蓝点。

我已经给出了这种类型的答案。检查此Link。但那是在 Swift 2.x 中。我在这个答案中发布的是 Swift 3.x

【讨论】:

  • 太棒了。我想知道,如果您使用的是didUpdateLocation ,是否需要添加plist Privacy - ..
  • 是的,必须在 plist 中添加条目才能激活相应应用的位置访问权限。
【解决方案2】:

这有点详细,所以我想留下一个完整的答案。这是我在几年前弄清楚基础知识以来遇到的零位置的最常见原因。因此,您在 viewDidLoad 中调用 CLLocationManager.startLocating()。然后调用设置地图的方法。有时这是可行的,有时则不是,这是因为 CLLocationManager 一方面在代码的另一部分设置权限并访问用户的位置所花费的时间量所导致的竞争条件。让我们看一下它不起作用的事件顺序:

1) 你调用 requestAlwaysAuthroization 和 startLocating 2) 用户权限设置在一个线程上触发 3)在您的 ViewController 中,您请求用户的位置,以设置您的地图 4)它返回零 5) 现在,第 2 步完成,应用可以访问用户的位置,但为时已晚

核心问题是,从请求权限和位置开始的过程需要几毫秒以上的时间。如果您的视图已经设置好,它需要几毫秒才能通过您的 viewDidLoad 中的方法。当您拥有所需的位置时,您已经请求了它。这导致我在基于位置的应用程序中发生了太多崩溃。

我的解决方法是制作一个单例 CLLocationManager,让我的起始视图成为一个委托,并在该视图中 requestAlwaysAuthorization 和 startLocating。这样,当我到达需要位置的视图时,应用程序已经开始定位,并且 locationManager.location 不为零。

这种方法显然不适用于所有应用。如果您需要澄清,请告诉我,如果您还需要代码,请告诉我。我有一些公开的 iO git 存储库,其中包含我遇到并解决了这个问题的项目。

【讨论】:

  • Hiii dylanthelion,感谢您的帮助。你可以分享演示吗?
  • 查看这个未完成应用程序的 Develop 分支:github.com/dylanthelion/AssassinationClient 要查看的两件事是 LocationManager.swift,它是一个单例,并在 startLocating 中调用开始跟踪位置所需的方法,以及LoginViewController,这是应用程序中的第一个视图,并在应用程序启动时立即开始跟踪位置。
  • 另外,它是 Swift 3 之前的版本,可能会构建也可能不会构建。但是编码模式相对容易实现,应该可以解决我描述的问题。
  • @dylanthelion 对于谷歌地图,我们不需要任何CLLocationManager。我们只需要在 plist 中添加键。
  • @RajanMaheshwari:我看到 ViewController 是一个 CLLocationManagerDelegate,这让我认为 CLLocationManager 处于活动状态,应该公开用户的位置。不过,我可以推荐您的 GoogleMaps 特定答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-01
  • 1970-01-01
  • 2017-03-06
  • 2015-08-14
  • 1970-01-01
  • 2020-02-29
相关资源
最近更新 更多