当前位置无法在Google地图中使用

时间:2016-10-15 04:15:45

标签: ios swift google-maps swift3 cllocationmanager

我在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
    }
}

2 个答案:

答案 0 :(得分:21)

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

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

enter image description here

另外,请确保您调用了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

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

enter image description here

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

答案 1 :(得分:0)

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

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

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

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

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