You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift4中GoogleMaps路径显示及跨控制器两点耗时绘制问题

在Swift 4中实现Google Maps路径显示与跨控制器地点耗时计算

一、先搞定跨控制器的地点数据传递

你已经在HomeViewController里通过PickupLocationDelegate拿到了第一个地点(起点),现在需要处理第二个地点(终点)的获取和传递。这里推荐用Delegate模式或者闭包回调,比通知更清晰,耦合性更低:

1. 定义终点选择的Delegate协议

假设第二个地点来自DestinationViewController,先定义一个代理协议:

protocol DestinationLocationDelegate: AnyObject {
    func didSelectDestinationPlace(place: GooglePlaceModel?)
}

2. 在终点选择控制器中添加代理属性

class DestinationViewController: UIViewController {
    weak var delegate: DestinationLocationDelegate?
    
    // 假设用户选择终点后触发这个方法
    func userConfirmedDestination(_ selectedPlace: GooglePlaceModel) {
        delegate?.didSelectDestinationPlace(place: selectedPlace)
        navigationController?.popViewController(animated: true)
    }
}

3. 在HomeViewController中保存双地点并触发后续逻辑

让HomeViewController遵守新的Delegate,同时保存起点和终点,拿到双地点后就可以调用路径绘制和耗时计算:

class HomeViewController: UIViewController, PickupLocationDelegate, DestinationLocationDelegate {
    // 存储起点和终点
    private var pickupPlace: GooglePlaceModel?
    private var destinationPlace: GooglePlaceModel?
    
    // 你的现有代码:获取起点
    func didSelectLocation(place: GooglePlaceModel?) {
        guard let place = place else { return }
        pickupPlace = place
        enter_Location_TF.text = place.name
        customDirectionViewTwo.isHidden = false
        direction_Button.isHidden = true
        location_Button.setImage(UIImage(named: "directionPoint")?.withRenderingMode(.alwaysOriginal), for: .normal)
    }
    
    // 新增:获取终点并触发路线逻辑
    func didSelectDestinationPlace(place: GooglePlaceModel?) {
        guard let place = place else { return }
        destinationPlace = place
        // 双地点都已获取,开始请求路线
        fetchRouteAndDuration()
    }
    
    // 跳转到终点选择页时设置代理
    func navigateToDestinationPicker() {
        let destVC = DestinationViewController()
        destVC.delegate = self
        navigationController?.pushViewController(destVC, animated: true)
    }
}

二、调用Google Directions API获取路线与耗时

要显示路径和计算耗时,需要调用Google Directions API,拿到路线坐标和时长数据:

1. 配置API密钥并发起网络请求

确保你已经集成Google Maps SDK,且API密钥启用了Directions API:

import GoogleMaps

// 替换为你的Google API密钥
let googleAPIKey = "YOUR_GOOGLE_API_KEY"

extension HomeViewController {
    func fetchRouteAndDuration() {
        guard let pickup = pickupPlace, let destination = destinationPlace else {
            print("缺少起点或终点数据")
            return
        }
        
        // 构造API请求URL
        let origin = "\(pickup.lat),\(pickup.lng)"
        let destCoord = "\(destination.lat),\(destination.lng)"
        let urlString = "https://maps.googleapis.com/maps/api/directions/json?origin=\(origin)&destination=\(destCoord)&key=\(googleAPIKey)"
        
        guard let url = URL(string: urlString) else { return }
        
        URLSession.shared.dataTask(with: url) { [weak self] data, _, error in
            guard let self = self, let data = data, error == nil else {
                print("路线请求失败:\(error?.localizedDescription ?? "未知错误")")
                return
            }
            
            do {
                // 用Codable解析API响应
                let response = try JSONDecoder().decode(DirectionsResponse.self, from: data)
                DispatchQueue.main.async {
                    self.drawRouteOnMap(with: response)
                    self.showTravelDuration(from: response)
                }
            } catch {
                print("路线数据解析失败:\(error.localizedDescription)")
            }
        }.resume()
    }
}

2. 定义Codable模型解析响应

简化版的模型,可根据需求扩展:

struct DirectionsResponse: Codable {
    let routes: [Route]
}

struct Route: Codable {
    let legs: [Leg]
    let overview_polyline: Polyline
}

struct Leg: Codable {
    let duration: Duration
}

struct Duration: Codable {
    let text: String // 格式化时长,如"20 mins"
    let value: Int // 秒数
}

struct Polyline: Codable {
    let points: String // 编码的路线坐标字符串
}

三、在Google Map上绘制路径

拿到编码的坐标串后,解码并绘制Polyline:

extension HomeViewController {
    func drawRouteOnMap(with response: DirectionsResponse) {
        guard let route = response.routes.first else { return }
        
        // 解码Polyline坐标
        let path = GMSPath(fromEncodedPath: route.overview_polyline.points)
        let polyline = GMSPolyline(path: path)
        polyline.strokeWidth = 4.0
        polyline.strokeColor = UIColor.systemBlue
        // 假设你的地图视图是mapView
        polyline.map = self.mapView
        
        // 调整地图视角,完整显示路线
        let bounds = GMSCoordinateBounds(path: path!)
        let cameraUpdate = GMSCameraUpdate.fit(bounds, withPadding: 50.0)
        self.mapView.moveCamera(cameraUpdate)
    }
}

四、显示两点间的预计耗时

从API响应中提取时长数据,显示到UI上:

extension HomeViewController {
    func showTravelDuration(from response: DirectionsResponse) {
        guard let leg = response.routes.first?.legs.first else { return }
        let durationText = leg.duration.text
        // 假设你有一个UILabel用于显示耗时
        durationLabel.text = "预计耗时:\(durationText)"
    }
}

关键注意事项

  • 确保你的GooglePlaceModel包含lat(纬度)和lng(经度)属性,否则无法构造API请求。
  • 在Info.plist中添加NSLocationWhenInUseUsageDescription,Google Maps需要位置权限才能正常工作。
  • 要处理网络请求失败的场景,比如给用户弹出提示框。
  • 如果需要实时更新路线,可以监听用户位置变化,重新发起路线请求。

内容的提问来源于stack exchange,提问作者Rohit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:30:15