[英]Google Maps iOS SDK, Getting Directions between 2 locations
當我使用谷歌地圖 SDK 時,我正在嘗試獲取 iOS 上兩個位置之間的行車方向。我知道我們可以使用兩種方法來做到這一點:-
1.) 使用URL Scheme,需要在您的設備上安裝Google Maps App。
2.) 使用方向 API,通過請求-響應,然后解析 JSON。顯示標記以顯示方向。
現在,我的問題是我可以通過其他方式在 iOS 上執行此操作嗎? 我需要顯示從我當前位置到我有緯度/經度的特定位置的方向。
我的意思是真的不可能簡單地傳遞 2 個位置作為參數和谷歌地圖 SDK,會給我指示嗎?
謝謝,
NSString *urlString = [NSString stringWithFormat:
@"%@?origin=%f,%f&destination=%f,%f&sensor=true&key=%@",
@"https://maps.googleapis.com/maps/api/directions/json",
mapView.myLocation.coordinate.latitude,
mapView.myLocation.coordinate.longitude,
destLatitude,
destLongitude,
@"Your Google Api Key String"];
NSURL *directionsURL = [NSURL URLWithString:urlString];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:directionsURL];
[request startSynchronous];
NSError *error = [request error];
if (!error) {
NSString *response = [request responseString];
NSLog(@"%@",response);
NSDictionary *json =[NSJSONSerialization JSONObjectWithData:[request responseData] options:NSJSONReadingMutableContainers error:&error];
GMSPath *path =[GMSPath pathFromEncodedPath:json[@"routes"][0][@"overview_polyline"][@"points"]];
GMSPolyline *singleLine = [GMSPolyline polylineWithPath:path];
singleLine.strokeWidth = 7;
singleLine.strokeColor = [UIColor greenColor];
singleLine.map = self.mapView;
}
else NSLog(@"%@",[request error]);
注意:確保您的 Google Direction API Sdk 在您的 google 開發者控制台中啟用。
聽起來您正在尋找像 Google Maps 應用程序那樣顯示路線的 UI Chrome。 適用於 iOS 的 Google Maps SDK 將為您繪制地圖,但您需要負責額外的導航鑲邊。
您可以使用Google Directions API請求路線,然后使用從服務返回的編碼路徑使用GMSPath 的 pathFromEncodedPath:方法繪制GMSPolyline 。
這些線顯示給定緯度/經度和用戶位置之間的位置;
NSString *googleMapUrlString = [NSString stringWithFormat:@"http://maps.google.com/?saddr=%f,%f&daddr=%@,%@", mapView.userLocation.coordinate.latitude, mapView.userLocation.coordinate.longitude, destinationLatitude, destinationLongtitude];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:googleMapUrlString]];
Swift 3.0 & XCode 8.0使用 AFNetworking & SwiftJson
let destLatitude="26.9124"
let destLongitude="75.7873"
mapView.isMyLocationEnabled = true
var urlString = "\("https://maps.googleapis.com/maps/api/directions/json")?origin=\("28.7041"),\("77.1025")&destination=\(destLatitude),\(destLongitude)&sensor=true&key=\("Your-Api-key")"
urlString = urlString.addingPercentEncoding( withAllowedCharacters: .urlQueryAllowed)!
let manager=AFHTTPRequestOperationManager()
manager.responseSerializer = AFJSONResponseSerializer(readingOptions: JSONSerialization.ReadingOptions.allowFragments) as AFJSONResponseSerializer
manager.requestSerializer = AFJSONRequestSerializer() as AFJSONRequestSerializer
manager.responseSerializer.acceptableContentTypes = NSSet(objects:"application/json", "text/html", "text/plain", "text/json", "text/javascript", "audio/wav") as Set<NSObject>
manager.post(urlString, parameters: nil, constructingBodyWith: { (formdata:AFMultipartFormData!) -> Void in
}, success: { operation, response -> Void in
//{"responseString" : "Success","result" : {"userId" : "4"},"errorCode" : 1}
//if(response != nil){
let parsedData = JSON(response)
print_debug("parsedData : \(parsedData)")
var path = GMSPath.init(fromEncodedPath: parsedData["routes"][0]["overview_polyline"]["points"].string!)
//GMSPath.fromEncodedPath(parsedData["routes"][0]["overview_polyline"]["points"].string!)
var singleLine = GMSPolyline.init(path: path)
singleLine.strokeWidth = 7
singleLine.strokeColor = UIColor.green
singleLine.map = self.mapView
//let loginResponeObj=LoginRespone.init(fromJson: parsedData)
// }
}, failure: { operation, error -> Void in
print_debug(error)
let errorDict = NSMutableDictionary()
errorDict.setObject(ErrorCodes.errorCodeFailed.rawValue, forKey: ServiceKeys.keyErrorCode.rawValue as NSCopying)
errorDict.setObject(ErrorMessages.errorTryAgain.rawValue, forKey: ServiceKeys.keyErrorMessage.rawValue as NSCopying)
})
斯威夫特 4.1,Xcode 9.4.1
//Here you need to set your origin and destination points and mode
let url = NSURL(string: "https://maps.googleapis.com/maps/api/directions/json?origin=Machilipatnam&destination=Vijayawada&mode=driving")
//OR if you want to use latitude and longitude for source and destination
//let url = NSURL(string: "\("https://maps.googleapis.com/maps/api/directions/json")?origin=\("17.521100"),\("78.452854")&destination=\("15.1393932"),\("76.9214428")")
let task = URLSession.shared.dataTask(with: url! as URL) { (data, response, error) -> Void in
do {
if data != nil {
let dic = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableLeaves) as! [String:AnyObject]
// print(dic)
let status = dic["status"] as! String
var routesArray:String!
if status == "OK" {
routesArray = (((dic["routes"]!as! [Any])[0] as! [String:Any])["overview_polyline"] as! [String:Any])["points"] as! String
// print("routesArray: \(String(describing: routesArray))")
}
DispatchQueue.main.async {
let path = GMSPath.init(fromEncodedPath: routesArray!)
let singleLine = GMSPolyline.init(path: path)
singleLine.strokeWidth = 6.0
singleLine.strokeColor = .blue
singleLine.map = mapView
}
}
} catch {
print("Error")
}
}
task.resume()
在這里,您需要將您的密鑰(google api 密鑰)添加到上述 API 中。
我已經這樣做了,因為它還在地圖上用DIRECTION ROUTE顯示引腳距離和持續時間。 但不要忘記在您的GOOGLE 開發者控制台中將您的GOOGLE DIRECTION API設置為啟用
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager.requestSerializer setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
NSString *urlString =@"https://maps.googleapis.com/maps/api/directions/json";
NSDictionary *dictParameters = @{@"origin" : [NSString stringWithFormat:@"%@",_sourceAdd], @"destination" : [NSString stringWithFormat:@"%@",_destinationAdd], @"mode" : @"driving", @"key":@"AIzaSyD9cWTQkAxemELVXTNUCALOmzlDv5b9Dhg"};
[manager GET:urlString parameters:dictParameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
GMSPath *path =[GMSPath pathFromEncodedPath:responseObject[@"routes"][0][@"overview_polyline"][@"points"]];
NSDictionary *arr=responseObject[@"routes"][0][@"legs"];
NSMutableArray *loc=[[NSMutableArray alloc]init];
loc=[[arr valueForKey:@"start_location"]valueForKey:@"lat"];
_sourceloc.latitude=[loc[0] doubleValue];
loc=[[arr valueForKey:@"start_location"]valueForKey:@"lng"];
_sourceloc.longitude=[loc[0] doubleValue];
loc=[[arr valueForKey:@"end_location"]valueForKey:@"lat"];
_destinationloc.latitude=[loc[0] doubleValue];
loc=[[arr valueForKey:@"end_location"]valueForKey:@"lng"];
_destinationloc.longitude=[loc[0] doubleValue];
NSString *dis,*dur;
loc=[[arr valueForKey:@"distance"]valueForKey:@"text"];
dis=loc[0];
loc=[[arr valueForKey:@"duration"]valueForKey:@"text"];
dur=loc[0];
NSString *sa,*da;
loc=[arr valueForKey:@"start_address"];
sa=loc[0];
loc=[arr valueForKey:@"end_address"];
da=loc[0];
UIAlertView *av=[[UIAlertView alloc]initWithTitle:@"Route Info" message:[NSString stringWithFormat:@"Distance:%@ \nDuration:%@",dis,dur] delegate:nil cancelButtonTitle:@"Okay" otherButtonTitles:nil, nil];
[av show];
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:_sourceloc.latitude longitude:_sourceloc.longitude zoom:10];
mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
GMSMarker *marker = [GMSMarker markerWithPosition:_sourceloc];
marker.title=@"Source";
marker.snippet =sa;
marker.appearAnimation = kGMSMarkerAnimationPop;
marker.map = mapView;
GMSMarker *marker2 = [GMSMarker markerWithPosition:_destinationloc];
marker2.title=@"Destination";
marker2.snippet =da;
marker2.appearAnimation = kGMSMarkerAnimationPop;
marker2.map = mapView;
GMSPolyline *singleLine = [GMSPolyline polylineWithPath:path];
singleLine.strokeWidth = 4;
singleLine.strokeColor = [UIColor blueColor];
singleLine.map = mapView;
self.view = mapView;
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
使用Swift我肯定是這樣解決的。
我的目的是找到兩個坐標之間的距離:
import AFNetworking
/**
Calculate distance between two valid coordinates
- parameter origin: origin coordinates
- parameter destination: destination coordinates
- parameter completion: completion callback
*/
func calculateDistance(origin origin: CLLocation, destination: CLLocation, completion: (distance: Double?) -> Void) {
let service = "https://maps.googleapis.com/maps/api/directions/json"
let originLat = origin.coordinate.latitude
let originLong = origin.coordinate.longitude
let destLat = destination.coordinate.latitude
let destLong = destination.coordinate.longitude
let urlString = "\(service)?origin=\(originLat),\(originLong)&destination=\(destLat),\(destLong)&mode=driving&units=metric&sensor=true&key=<YOUR_KEY>"
let directionsURL = NSURL(string: urlString)
let request = NSMutableURLRequest(URL: directionsURL!)
request.HTTPMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let operation = AFHTTPRequestOperation(request: request)
operation.responseSerializer = AFJSONResponseSerializer()
operation.setCompletionBlockWithSuccess({ (operation: AFHTTPRequestOperation!, responseObject: AnyObject!) -> Void in
if let result = responseObject as? NSDictionary {
if let routes = result["routes"] as? [NSDictionary] {
if let lines = routes[0]["overview_polyline"] as? NSDictionary {
if let points = lines["points"] as? String {
let path = GMSPath(fromEncodedPath: points)
let distance = GMSGeometryLength(path)
print("wow \(distance / 1000) KM")
}
}
}
}
}) { (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in
print("\(error)")
}
operation.start()
}
(void)viewDidLoad {
[super viewDidLoad];
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:30.692408
longitude:76.767556
zoom:14];
GMSMapView *mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
mapView.myLocationEnabled = YES;
// Creates markers in the center of the map.
GMSMarker *marker = [[GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake(30.6936659, 76.77201819999999);
marker.title = @"Chandigarh 47c";
marker.snippet = @"Hello World";
marker.map = mapView;
GMSMarker *marker1 = [[GMSMarker alloc] init];
marker1.position = CLLocationCoordinate2DMake(30.742138, 76.818756);
marker1.title = @"Sukhna Lake";
marker1.map = mapView;
//creating a path
GMSMutablePath *path = [GMSMutablePath path];
[path addCoordinate:CLLocationCoordinate2DMake(@(30.6936659).doubleValue,@(76.77201819999999).doubleValue)];
[path addCoordinate:CLLocationCoordinate2DMake(@(30.742138).doubleValue,@(76.818756).doubleValue)];
GMSPolyline *rectangle = [GMSPolyline polylineWithPath:path];
rectangle.strokeWidth = 2.f;
rectangle.map = mapView;
self.view=mapView;
}
如果有人想解析與路由數組的距離,則以下是在 swift 4/5 中獲取距離的方法
let distance = responseJSON["routes"][0]["legs"][0]["distance"]["text"]
正如@iOS 建議的那樣,我也發布了我的答案,向您展示如何使用 Codable 和 Alamofire/Moya 來完成它。
為此,您必須重構 GoogleMaps 響應實體,如下所示:
/// 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?
}
您可以看到響應對象如何由路由數組和狀態字符串(例如"OK"
)組成。 每條路線都有一些屬性,包括overview_polyline
字段。 為了能夠通過JSONDecoder
對該對象進行解碼,您還需要對該類進行建模(它只包含關鍵points
的字符串值。
現在,如果您只需要overview_polyline
,只要您仍然對響應的層次結構進行建模(例如 GMSDirectionsResponse > GMSRoute > OverviewPolyline > points
),忽略所有其他不需要的屬性和結構就完全沒points
。
您現在可以做的是要求JSONDecoder
用GMSDirectionsResponse
從正文數據中解碼GMSDirectionsResponse
! 在我的項目中,我使用了Moya,但我相信您也可以使用URLSession
的data
對象來實現。
// let moya do request
let moya = MoyaProvider<YourGMSService>()
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")
}
這可能看起來像大量的代碼,但它非常方便,並且可以防止您與 JSON 下標成員和大量[]
大括號混淆。 😊
如果您有任何問題,我很樂意為您提供幫助!
在谷歌開發者控制台中創建一個密鑰,確保您的項目是使用 App bundleID 創建的,然后添加以下代碼
NSString *KEY=@"";
NSString *Origin=@"";
NSString *Destination=@"";
NSString *str_maps=[NSString stringWithFormat:@"https://maps.googleapis.com/maps/api/directions/json?origin=%@&destination=%@&key=%@",Origin,Destination,KEY];
NSURL *url=[NSURL URLWithString:str_maps];
NSData *dta=[NSData dataWithContentsOfURL:url];
NSDictionary *dict=(NSDictionary *)[NSJSONSerialization JSONObjectWithData:dta options:kNilOptions error:nil];
NSLog(@"%@",dict);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.