【问题标题】:Cannot display info from Google directions JSON in map marker - iOS Swift app无法在地图标记中显示来自 Google 方向 JSON 的信息 - iOS Swift 应用
【发布时间】:2015-04-27 16:56:13
【问题描述】:

我尝试使用 Google Directions API 获取从我的位置到地图上选定标记的距离和持续时间。我正在使用 Alamofire + SwiftyJSON 来执行 HTTP 请求并解析我返回的 JSON。

我使用这种方法来请求和解析 JSON:

    func fetchDistanceFrom(from: CLLocationCoordinate2D, to: CLLocationCoordinate2D, completionHandler: (String?, String?, NSError?) -> ()) -> ()
{
    let urlString = "https://maps.googleapis.com/maps/api/directions/json?key=\(apiKey)&origin=\(from.latitude),\(from.longitude)&destination=\(to.latitude),\(to.longitude)&mode=walking"

    var parsedDistance : String?
    var parsedDuration : String?

    request(.GET, urlString)
        .responseJSON { (req, res, json, error) in
            if(error != nil) {
                NSLog("Error: \(error)")
            }
            else {
                var json = JSON(json!)
                parsedDistance = json["routes"][0]["legs"][0]["distance"]["text"].stringValue as String!
                parsedDuration = json["routes"][0]["legs"][0]["duration"]["text"].stringValue as String!
                dispatch_async(dispatch_get_main_queue()) {
                    completionHandler(parsedDistance, parsedDuration, error)
                }
            }
    }
}

我在我的 MapView 类中这样使用它:

func mapView(mapView: GMSMapView!, didTapMarker marker: GMSMarker!) -> Bool {
    let selectedMarker = marker as! ExtendedMarker

    dataProvider.fetchDistanceFrom(mapView.myLocation.coordinate, to: marker.position){ (parsedDistance, parsedDuration, error) in

        let busStopDistance = parsedDistance
        let busStopDuration = parsedDuration

            selectedMarker.distance = "Distance: \(busStopDistance!)"
            selectedMarker.duration = "Duration: \(busStopDuration!)"
    }
    return false
}

之后在此方法中显示信息:

    func mapView(mapView: GMSMapView!, markerInfoContents marker: GMSMarker!) -> UIView! {
    let selectedMarker = marker as! ExtendedMarker

    if let infoView = UIView.viewFromNibName("MarkerInfoView") as? MarkerInfoView {

        infoView.nameLabel.text = selectedMarker.name
        infoView.linesTextView.text = selectedMarker.lines
        infoView.distanceLabel.text = selectedMarker.distance
        infoView.durationLabel.text = selectedMarker.duration

        return infoView
    } else {
        return nil
    }
}

但它没有按预期工作,因为我第一次单击地图上的标记时不知何故无法获得距离和时间。它总是在第二次点击标记时出现。看起来我从 Google 获得了 JSON 对象,只是在 MapView 显示标记信息之前没有对其进行解析。

请问有什么办法可以解决这个问题吗?我会非常感谢任何建议。谢谢。

【问题讨论】:

  • 不需要dispatch_async(dispatch_get_main_queue()),因为主队列中已经调用了返回块。
  • 我认为您需要在下载数据后刷新地图标记,因为我认为您不能出于某种原因只更新它们。我在点击标记时异步下载图像时遇到了类似的问题。
  • 感谢您为我指明了正确的方向,我现在可以正常工作了 :)

标签: ios json google-maps swift


【解决方案1】:

我已经通过在 didTapMarker 方法中强制刷新标记来使其工作,如下所示:

func mapView(mapView: GMSMapView!, didTapMarker marker: GMSMarker!) -> Bool {
    let selectedMarker = marker as! ExtendedMarker

    dataProvider.fetchDistanceFrom(mapView.myLocation.coordinate, to: marker.position){ (parsedDistance, parsedDuration, error) in

        let busStopDistance = parsedDistance
        let busStopDuration = parsedDuration

            selectedMarker.distance = "Distance: \(busStopDistance!)"
            selectedMarker.duration = "Duration: \(busStopDuration!)"

            mapView.selectedMarker = nil;
            mapView.selectedMarker = selectedMarker;
    }
    return false
}

【讨论】:

    【解决方案2】:

    使用 swift 2.0 和 Alamomfire 获取距离 google maps sdk ios:

    //get Distance two points
    func getDistanceFrom(de: CLLocationCoordinate2D, para: CLLocationCoordinate2D){
    
        let urlString = "https://maps.googleapis.com/maps/api/directions/json?key=\(GoogleMapsApiKey)&origin=\(de.latitude),\(de.longitude)&destination=\(para.latitude),\(para.longitude)&mode=walking"
    
        Alamofire.request(.POST, urlString, parameters: nil, encoding: .JSON, headers: nil)
    
            .responseJSON { (retorno) -> Void in
                //print(retorno.result.value)
    
                if retorno.result.isSuccess {
                    if let km = retorno.result.value?.objectForKey("routes")?[0].objectForKey("legs")?[0].objectForKey("distance") as? NSDictionary{
    
                        if let km_KM = km.valueForKey("text") as? String {
                            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                                self.LB_DistanciaKM.text = km_KM
                            })
                        }
                    }
                }
        }
    }
    

    【讨论】:

      【解决方案3】:

      使用 Swift 3 和 Alamofire

      func getGoogleMapGeoCodeDurationWithAlamofire(url: String) {
              Alamofire.request(url).responseJSON { response in
                  let result = response.result
                  if let result = result.value as? Dictionary<String, AnyObject> {
                      if let routes = result["routes"] as? [Dictionary<String, AnyObject>] {
                          if let distance = routes[0]["legs"] as? [Dictionary<String, AnyObject>] {
                              print(distance[0]["distance"]?["text"] as! String)
                              print(distance[0]["duration"]?["text"] as! String)
      
                          }
                      }
                  }
              }
      
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-24
        • 1970-01-01
        • 2014-11-10
        • 2017-07-13
        • 2016-01-20
        • 1970-01-01
        相关资源
        最近更新 更多