【问题标题】:Finding Driving/Walking distance between 2 locations in Swift 3 using Google Maps API使用 Google Maps API 在 Swift 3 中查找 2 个位置之间的驾驶/步行距离
【发布时间】:2017-04-26 14:15:04
【问题描述】:

我正在尝试使用 Google Maps API 获取两个位置之间的行车/步行距离。我正在将我的应用程序从 Objective-c 更新到 Swift 3,现在我一直坚持将这段代码转换为 Swift 3。

NSString *dist;
NSString *strUrl = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/directions/json?origin=%f,%f&destination=%f,%f&sensor=false&mode=%@", closestLocation.coordinate.latitude,  closestLocation.coordinate.longitude, _currentUserLocation.coordinate.latitude,  _currentUserLocation.coordinate.longitude, @"DRIVING"];
NSURL *url = [NSURL URLWithString:[strUrl stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet]];
NSData *jsonData = [NSData dataWithContentsOfURL:url];
if(jsonData != nil)
{
    NSError *error = nil;
    id result = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
    NSMutableArray *arrDistance=[result objectForKey:@"routes"];
    if ([arrDistance count]==0) {
        NSLog(@"N.A.");
    }
    else{
        NSMutableArray *arrLeg=[[arrDistance objectAtIndex:0]objectForKey:@"legs"];
        NSMutableDictionary *dictleg=[arrLeg objectAtIndex:0];

        dist = [NSString stringWithFormat:@"%@",[[dictleg   objectForKey:@"distance"] objectForKey:@"text"]];
    }
}
else{
    NSLog(@"N.A.");
}

我尝试使用 Swiftify 之类的工具,但处处出错。我现在拥有的是:

var dist: String = ""
var strUrl: String = "http://maps.googleapis.com/maps/api/directions/json?origin=\(closestLocation!.coordinate.latitude),\(closestLocation!.coordinate.longitude)&destination=\(currentUserLocation!.coordinate.latitude),\(currentUserLocation!.coordinate.longitude)&sensor=false&mode=\("DRIVING")"
var url = URL(string: strUrl)
var jsonData = Data(contentsOf: url!)
    if (jsonData != nil) {
        var error: Error? = nil
        var result: Any? = try? JSONSerialization.jsonObject(with: jsonData, options: JSONSerialization.ReadingOptions.Element.mutableContainers)
        var arrDistance: [Any]? = (result?["routes"] as? [Any])
        if arrDistance?.count == 0 {
            print("N.A.")
        }
        else {
            var arrLeg: [Any]? = ((arrDistance?[0] as? [Any])?["legs"] as? [Any])
            var dictleg: [AnyHashable: Any]? = (arrLeg?[0] as? [AnyHashable: Any])

            dist = "\(dictleg?["distance"]["text"])"
        }
    }
    else {
        print("N.A.")
    }

我现在的错误如下:

使用 Data(contentsOf: url!) 它告诉我“调用可以抛出,但它没有标有 'try' 并且错误未处理

而且它不喜欢我如何将 [Any] 用于我的 arrDistance 变量。

如果有人知道如何在 Swift 3 中实现这个 API 调用,那将非常有帮助。谢谢

【问题讨论】:

  • 与问题无关,但您不应使用 Data(contentsOf: url!) 下载数据。你应该使用 URLSession dataTask(with: URL)
  • 但是你为什么使用谷歌的 API 而不是苹果内部的?

标签: swift google-maps swift3


【解决方案1】:

什么编译器说Data(contentsOf:) 会出现throws 异常,所以你需要用do catch 块来处理它。现在正如评论中所建议的,您需要使用dataTask(with:) 而不是Data(contentsOf:) 来下载数据。您也可以使用您的代码制作完成块,因此请在您的代码中进行如下更改。

func getDistance(completion: @escaping(String) -> Void) {

    var dist = ""
    let strUrl = "http://maps.googleapis.com/maps/api/directions/json?origin=\(closestLocation!.coordinate.latitude),\(closestLocation!.coordinate.longitude)&destination=\(currentUserLocation!.coordinate.latitude),\(currentUserLocation!.coordinate.longitude)&sensor=false&mode=\("DRIVING")"
    let url = URL(string: strUrl)!
    let task = URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in
        guard let data = data, error == nil else {
            print(error?.localizedDescription ?? "")
            completion(dist)
            return
        }
        if let result = (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String:Any],
            let routes = result["routes"] as? [[String:Any]], let route = routes.first,
            let legs = route["legs"] as? [[String:Any]], let leg = legs.first,
            let distance = leg["distance"] as? [String:Any], let distanceText = distance["text"] as? String {

            dist = distanceText
        }
        completion(dist)
    })
    task.resume()
}

现在只需像这样调用getDistance函数。

self.getDistance { (distance) in
    //Update UI on main thread
    DispatchQueue.main.async {
        print(distance)
        self.label.text = distance
    }
}

【讨论】:

  • 但是我遇到了无法存储该距离变量值的问题。我正在尝试将该值放在我的一个视图控制器上的标签上
  • @trludt 不要像 self.getDistance { (distance) in yourLabel.text = distance } 那样在完成 getDistance 时简单地设置标签文本而不是 print 语句
  • 标签需要一段时间才能显示值。它在技术上有效,但我需要在视图加载后立即显示该信息。
  • @trludt 完成块调用取决于您的网络速度,但如果您得到响应并且仍然需要时间来更新 UI 而不是在主线程上进行 UI 更改,因此请将您的 UI 更改代码放入 @987654334 @
  • 所以我将 self.getDistance 函数放在 DispatchQueue.main.async { } 中并通过那里更新 UI,但更新仍然需要将近 20-30 秒。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-14
  • 1970-01-01
  • 2012-01-18
  • 1970-01-01
  • 2012-08-31
  • 1970-01-01
  • 2015-03-30
相关资源
最近更新 更多