Google Maps iOS SDK, Getting Directions between 2 locations

前端 未结 11 1288
栀梦
栀梦 2020-12-02 07:52

While I am using Google Maps SDK, I am trying to get driving direction between two locations on iOS. I know we can do this using two methods:-

1.) Using URL Scheme,

11条回答
  •  [愿得一人]
    2020-12-02 08:49

    As @iOS suggested I'm also posting my answer to show you a way how to accomplish it using Codable and Alamofire/Moya.

    To do so, you'd have to remodel the GoogleMaps Response entities, like so:

    /// Struct for modelling a response from the Google Maps Directions API. This is the "root level"
    struct GMSDirectionsResponse: Codable {
        /// The suggested routes
        let routes: [GMSRoute]
        /// Status telling if request was okay
        let status: String
    }
    /// Struct for modelling a Route suggested by GoogleMaps Directions API.
    struct GMSRoute: Codable {
        /// Represents an area in the map
        struct Bounds: Codable {
            // You can omit these structs for your case. 
            // Just to give an idea how it would look like if you model the entire response
            // ...
        }
        
        struct Leg: Codable {
            // ...
        }
        
        /// A single step of a route
        struct Step: Codable {
            // ...
        }
        
        /// Structure around the coded representation of the GMSPath
        struct OverviewPolyline: Codable {
            /// A coded representation of the GMSPath
            let points: String
        }
        
        /// The bounds to show on the map to include the whole route
        let bounds: Bounds?
        /// All legs of this route, including the single steps
        let legs: [Leg]?
        /// The path to walk/drive/etc. this route
        let overview_polyline: OverviewPolyline?
        /// A textual summary of the most important roads to take
        let summary: String?
    }
    
    
    

    You can see how a response object consists of an array of routes and a status string (e.g. "OK"). Each route has a few properties again, including the overview_polyline field. For being able to have that object decoded by a JSONDecoder you also need to model that class (it simply contains a string value for the key points.

    Now if you only need the overview_polyline it's perfectly fine to omit all other unneeded properties and structs as long as you still model the hierarchical structure of the response (e.g. GMSDirectionsResponse > GMSRoute > OverviewPolyline > points).

    What you can do now is to ask a JSONDecoder to decode a GMSDirectionsResponse from the body data with a single line! In my project I used Moya but I'm sure you can also do it with URLSession's data object.

    // let moya do request
    let moya = MoyaProvider()
    moya.request(.getDirections(origin: origin, destination: destination)) { (result) in
        switch result {
        case .success(let response):
            // check if request was successful
            if
                // makes sure status is code is 2xx
                (try? response.filterSuccessfulStatusCodes()) != nil,
                // this line tries to decode a GMSDirectionsResponse object from response.data
                let directions = try? JSONDecoder().decode(GMSDirectionsResponse.self, from: response.data)
            {
                // successful request, converted response to JSON Dictionary
                NSLog("GET DIRECTIONS: Success")
                
                // here we can check for the directions properites already!
                NSLog("GoogleMaps Directions request finished with status %@", directions.status)
                
                // check if we have at least one GMSRoute with an overview_polyline
                guard let encodedPath = directions.routes.first?.overview_polyline else { return }
                // now let's use the encoded path:
                DispatchQueue.main.async {
                    let path = GMSPath.init(fromEncodedPath: encodedPath.points)
                    
                    // continue as in other answers (Y)
                    let singleLine = GMSPolyline.init(path: path)
                    singleLine.strokeWidth = 6.0
                    singleLine.strokeColor = .blue
                    singleLine.map = mapView
                }
                return
            }
            // some error handling if we couldn't parse the data to a GMSDirectionsResponse object
            NSLog("Could not parse JSON from Directions API Response:\n%@", response.debugDescription)
        case .failure(let error):
            // we had an error
            NSLog(error.localizedDescription)
        }
        // log and complete with nil
        NSLog("GET DIRECTIONS: Failed")
    }
    

    This might look like a huge load of code but it's totally convenient and it keeps you from messing around with JSON subscript members and lots of [] braces.

提交回复
热议问题