I am trying to parse a JSON from Google to place annotations on Map. Parsing JSON using AFNetworking and parsing process is in Singleton class. I am getting values from two different JSON.
Places Autocomplete JSON of Google
Places Details JSON of Google
Here is my code for Singleton class
-(void)getData:(NSString *)searchString
{
_dataArray = [[NSMutableArray alloc]init];
NSString *requestString = [[NSString alloc]init];
requestString = [NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/autocomplete/json?input=%#&sensor=true&key=APIKEY",searchString];
requestString = [requestString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *URL = [NSURL URLWithString:requestString];
NSURLRequest *requestURL = [NSURLRequest requestWithURL:URL];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:requestURL success:^(NSURLRequest *requestURL,NSHTTPURLResponse *response, id JSON){
self.dataArray = [JSON objectForKey:#"predictions"];
[[NSNotificationCenter defaultCenter]postNotificationName:#"Doreload" object:nil];
}failure:^(NSURLRequest *requestURL,NSHTTPURLResponse *response,NSError *error, id JSON){
NSLog(#"Request Failed with Error: %#, %#", error, error.userInfo);
}];
[operation start];
}
-(void)detailList:(NSString *)referenceString
{
_detailArray = [[NSMutableArray alloc]init];
NSString *requestString = [[NSString alloc]initWithFormat:#"https://maps.googleapis.com/maps/api/place/details/json?reference=%#&sensor=true&key=APIKEY",referenceString];
NSURL *URL = [NSURL URLWithString:requestString];
NSURLRequest *requestURL = [NSURLRequest requestWithURL:URL];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:requestURL success:^(NSURLRequest *requestURL,NSHTTPURLResponse *response, id JSON){
self.detailArray = [JSON objectForKey:#"result"];
[[NSNotificationCenter defaultCenter]postNotificationName:#"showList" object:nil];
}failure:^(NSURLRequest *requestURL,NSHTTPURLResponse *response,NSError *error, id JSON){
}];
[operation start];
}
In ViewController with the first function I am passing the name of the Place in the tableView :
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
sharedRequest = [RequestHandler sharedRquest];
static NSString *cellID = #"Cell Identifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
cell.textLabel.text = [[sharedRequest.dataArray objectAtIndex:indexPath.row]objectForKey:#"description"];
[_spinner stopAnimating];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *details = [[DetailViewController alloc]initWithNibName:#"DetailViewController" bundle:nil];
details.stringReference = [[sharedRequest.dataArray objectAtIndex:indexPath.row]objectForKey:#"reference"];
[self.navigationController pushViewController:details animated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
And the Details Class is :
- (void)viewDidLoad
{
[super viewDidLoad];
[[RequestHandler sharedRquest]detailList:self.stringReference];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(showOnMap) name:#"showList" object:nil];
self.spinner = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
self.spinner.hidesWhenStopped = YES;
self.spinner.frame = CGRectMake(0, 0, 320, 480);
[self.view addSubview:_spinner];
[_spinner startAnimating];
self.mapView.showsUserLocation = TRUE;
self.mapView.delegate = self;
}
- (void)showOnMap:(NSNotification *)notification
{
NSLog(#"Entered");
sharedRequest = [RequestHandler sharedRquest];
NSString *string = [[NSString alloc]init];
string = [sharedRequest.detailArray valueForKey:#"name"];
self.label.text = string;
}
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
sharedRequest = [RequestHandler sharedRquest];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 30000, 30000);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
double latitude = [[[[sharedRequest.detailArray valueForKey:#"geometry"]objectForKey:#"location"]objectForKey:#"lat"]doubleValue];
double longitude =[[[[sharedRequest.detailArray valueForKey:#"geometry"]objectForKey:#"location"]objectForKey:#"lng"]doubleValue];
CLLocationCoordinate2D coord = { latitude, longitude };
MKPointAnnotation *point = [[MKPointAnnotation alloc]init];
point.coordinate = coord;
point.title = [sharedRequest.detailArray valueForKey:#"name"];
[self.mapView addAnnotation:point];
[_spinner stopAnimating];
}
The problem is in Details Class for the first time when using with break points it shows annotations and second it throughs an error:
-[__NSArrayI objectForKey:]: unrecognized selector sent to instance 0x86332e0
EDIT:
here is what shared.detailArray has:
"address_components" = (
{
"long_name" = Francestown;
"short_name" = Francestown;
types = (
locality,
political
);
},
{
"long_name" = Hillsborough;
"short_name" = Hillsborough;
types = (
"administrative_area_level_2",
political
);
},
{
"long_name" = "New Hampshire";
"short_name" = NH;
types = (
"administrative_area_level_1",
political
);
},
{
"long_name" = "United States";
"short_name" = US;
types = (
country,
political
);
}
);
"adr_address" = "<span class=\"locality\">Francestown</span>, <span class=\"region\">NH</span>, <span class=\"country-name\">USA</span>";
"formatted_address" = "Francestown, NH, USA";
geometry = {
location = {
lat = "42.9875";
lng = "-71.8130599";
};
viewport = {
northeast = {
lat = "43.03844";
lng = "-71.7474139";
};
southwest = {
lat = "42.949703";
lng = "-71.88583609999999";
};
};
};
icon = "http://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png";
id = ccd239475516163d29405af62fb286bedb4c6377;
name = Francestown;
reference = "CoQBcwAAAPSQxzNrepzPywLZr1PDoPEmQmGR8rIPTPoQ_f2kXpceRGHU_J_FEcrDxZSzebqLRpNYlUC_-xRJVV7Jx_mW1KJ33foU9y0ZCNK_kC1orqZVK5B-EONPD_Ef_e9WXXZdfOZTBQzNYLhoVdP8Ufa1bPe_vuuwe3rqYtf80IyANb8mEhCKi6kISip4ItpBFfgWjuGvGhSj0hURZaTQXX4lnFlxe2v4O5Uo6Q";
types = (
locality,
political
);
url = "https://maps.google.com/maps/place?q=Francestown&ftid=0x89e22c36ba6dc937:0x52cccc5f0f9b8663";
vicinity = Francestown;
}
I tried a lot to understand the error, but all in vain.
Any help would be appreciable.
Thanks
Hope this will help you if you are looking to achieve results using a different way.
I used NSJSONSerialization class to parse the json response from Google.
In this method I parse the NSMutable Data object- _routeData(created by appending data from Google response)
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSMutableArray *polyLinesArray = [[NSMutableArray alloc] init];
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:_routeData options:kNilOptions error:nil];
NSArray *locationArray = [[[[[jsonDict valueForKey:#"routes"]valueForKey:#"legs"]valueForKey:#"steps"]valueForKey:#"polyline"] valueForKey:#"points"];
if(locationArray.count > 0)
{
NSArray *polyLinePointsArray = [[locationArray objectAtIndex:0]objectAtIndex:0];
for (int i = 0; i < [polyLinePointsArray count]; i++)
{
NSString *encodedPoints = [polyLinePointsArray objectAtIndex:i];
MKPolyline *route = [self polylineWithEncodedString:encodedPoints];
[polyLinesArray addObject:route];
}
// remove previous overlays
if(_mapView.overlays.count > 0)
{
[_mapView removeOverlays:_mapView.overlays];
}
[self.mapView addOverlays:polyLinesArray];
}
}
To decode the polyline points response from Google I used a class I found on stackoverflow..
- (MKPolyline *)polylineWithEncodedString:(NSString *)encodedString
{
const char *bytes = [encodedString UTF8String];
NSUInteger length = [encodedString lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
NSUInteger idx = 0;
NSUInteger count = length / 4;
CLLocationCoordinate2D *coords = calloc(count, sizeof(CLLocationCoordinate2D));
NSUInteger coordIdx = 0;
float latitude = 0;
float longitude = 0;
while (idx < length) {
char byte = 0;
int res = 0;
char shift = 0;
do {
byte = bytes[idx++] - 63;
res |= (byte & 0x1F) << shift;
shift += 5;
} while (byte >= 0x20);
float deltaLat = ((res & 1) ? ~(res >> 1) : (res >> 1));
latitude += deltaLat;
shift = 0;
res = 0;
do {
byte = bytes[idx++] - 0x3F;
res |= (byte & 0x1F) << shift;
shift += 5;
} while (byte >= 0x20);
float deltaLon = ((res & 1) ? ~(res >> 1) : (res >> 1));
longitude += deltaLon;
float finalLat = latitude * 1E-5;
float finalLon = longitude * 1E-5;
CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(finalLat, finalLon);
coords[coordIdx++] = coord;
if (coordIdx == count) {
NSUInteger newCount = count + 10;
coords = realloc(coords, newCount * sizeof(CLLocationCoordinate2D));
count = newCount;
}
}
MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords count:coordIdx];
free(coords);
return polyline;
}
Instead of this
double latitude = [[[[sharedRequest.detailArray valueForKey:#"geometry"]objectForKey:#"location"]objectForKey:#"lat"]doubleValue];
double longitude =[[[[sharedRequest.detailArray valueForKey:#"geometry"]objectForKey:#"location"]objectForKey:#"lng"]doubleValue];
try this,
double latitude = [[[[sharedRequest.detailArray valueForKey:#"geometry"]valueForKey:#"location"]valueForKey:#"lat"]doubleValue];
double longitude =[[[[sharedRequest.detailArray valueForKey:#"geometry"]valueForKey:#"location"]valueForKey:#"lng"]doubleValue];
Found the Solution:
- (void)showOnMap:(NSNotification *)notification
{
NSLog(#"Entered");
sharedRequest = [RequestHandler sharedRquest];
NSString *string = [[NSString alloc]init];
string = [sharedRequest.detailArray valueForKey:#"name"];
self.label.text = string;
double latitude = [[[[sharedRequest.detailArray valueForKey:#"geometry"]objectForKey:#"location"]objectForKey:#"lat"]doubleValue];
double longitude =[[[[sharedRequest.detailArray valueForKey:#"geometry"]objectForKey:#"location"]objectForKey:#"lng"]doubleValue];
CLLocationCoordinate2D coord = { latitude, longitude };
MKPointAnnotation *point = [[MKPointAnnotation alloc]init];
point.coordinate = coord;
point.title = [sharedRequest.detailArray valueForKey:#"name"];
[self.mapView addAnnotation:point];
[_spinner stopAnimating];
}
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
sharedRequest = [RequestHandler sharedRquest];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 30000, 30000);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
}
Related
I have create a PolyLine in MapView. I tried to many times but did not draw. Ones a draw polyLine but that case run only simulator, I run in device and crash my app. and I already post my question here
I tried to many times and using lots of tutorials, please suggest any other tutorial.
I want to create a PolyLine in MapView using google direction URL. Starting point is my device location and end point is any lat long. so both points in centre draw a polyLine. That means create a root map starting point to end point draw a PolyLine.
Please help, Thank you
you can use google api for this
http://maps.googleapis.com/maps/api/directions/json?origin
in this api you have to pass lat log of your locations like this methode
-(NSArray*) calculateRoutes
{
NSString *baseUrl = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%f,%f&destination=%f,%f&sensor=true",currentlatitude,currentlongitude,destination lat,destination log];
NSData *data=[NSData dataWithContentsOfURL:[NSURL URLWithString:baseUrl]];
if (data) {
NSDictionary *direction_dictionary=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
if (direction_dictionary) {
if ([[direction_dictionary valueForKey:#"status"] isEqualToString:#"OK"]) {
NSArray *routes_array=[direction_dictionary valueForKey:#"routes"];
if (routes_array) {
NSString *poinstEncoded_String=[[[routes_array firstObject] valueForKey:#"overview_polyline"] valueForKey:#"points"];
routes = [self decodePolyLine:[poinstEncoded_String mutableCopy]];
NSInteger numberOfSteps = routes.count;
CLLocationCoordinate2D coordinates[numberOfSteps];
for (NSInteger index = 0; index < numberOfSteps; index++)
{
CLLocation *location = [routes objectAtIndex:index];
CLLocationCoordinate2D coordinate = location.coordinate;
coordinates[index] = coordinate;
}
MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:coordinates count:numberOfSteps];
dispatch_async(dispatch_get_main_queue(), ^{
[self.MapVw addOverlay:polyLine];
// add polyline here to your mapview
});
}
}
}
}
}
-(NSMutableArray *)decodePolyLine: (NSMutableString *)encoded
{
[encoded replaceOccurrencesOfString:#"\\\\" withString:#"\\" options:NSLiteralSearch range:NSMakeRange(0, [encoded length])];
NSInteger len = [encoded length];
NSInteger index = 0;
NSMutableArray *array = [[NSMutableArray alloc] init];
NSInteger lat=0;
NSInteger lng=0;
while (index < len)
{
NSInteger b;
NSInteger shift = 0;
NSInteger result = 0;
do
{
b = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
NSInteger dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do
{
b = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
NSInteger dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
lng += dlng;
NSNumber *latitude = [[NSNumber alloc] initWithFloat:lat * 1e-5];
NSNumber *longitude = [[NSNumber alloc] initWithFloat:lng * 1e-5];
CLLocation *loc = [[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]];
[array addObject:loc];
}
return array;
}
After getting response (Full example http://way2ios.com/development/ios-development-2/iphone-2/draw-polygon-mkmapview-stylus/):
– (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id )overlay
{
MKPolygonView *polygonView = [[MKPolygonView alloc] initWithPolygon:overlay];
polygonView.lineWidth = 5;
polygonView.strokeColor = [UIColor redColor];
polygonView.fillColor = [UIColor colorWithRed:0 green:191 blue:255 alpha:0.5];
mapView.userInteractionEnabled = YES;
return polygonView;
}
Check these also :
https://github.com/kadirpekel/MapWithRoutes and https://github.com/versluis/MapViewLines
i m showing user's location in a map view(apple map) with custom pin and those same pins are shown in a table view in front of the user name.Each user should have a different pin and if the user name occurs twice then it should have the same pin colour as the previous one.
This is the table view screen shot and below this table view there is a map view:
if in the table view "user name" has blue pin then in the map "username's" location shud be shown with blue pin.
if user2 has green pin in table, it should be green in map as well.
the response i m getting is
{
"driver_or_rider" = 1;
email = "ish#gmail.com";
isGuest = 0;
lat = "47.606209";
long = "-122.332071";
name = "ish bids";
"status_trip" = 1;
"user_image_url" = "http://app/image/1458101010.userimage";
},
{
"driver_or_rider" = 0;
email = "arin#gmail.com";
isGuest = 0;
lat = "34.052227";
long = "-118.243660";
name = "arin John";
"status_trip" = 1;
"user_image_url" = "http://app/image/5b3ee2e9fb51c7b20303a95b93bf63b2.";
},
{
"driver_or_rider" = 0;
email = "deepak12#gmail.com";
isGuest = 0;
lat = "31.968599";
long = "-99.901813";
name = "Deepak Chaudhary chaudhary ";
"status_trip" = 1;
"user_image_url" = "http://app/image/2197c75dc6b2bbd0ff26008a987781f3.";
},
{
"driver_or_rider" = 0;
email = "ish#gmail.com";
isGuest = 1;
lat = "31.968599";
long = "-99.901813";
name = "Deepak Chaudhary chaudhary 's Guest";
"status_trip" = 1;
"user_image_url" = "http://app/image/no-image.png";
},
{
"driver_or_rider" = 0;
email = "ish#gmail.com";
isGuest = 1;
lat = "41.878114";
long = "-87.629798";
name = "shiv Shankar 's Guest";
"status_trip" = 1;
"user_image_url" = "http://app/image/no-image.png";
},
{
"driver_or_rider" = 0;
email = "shiv#gmail.com";
isGuest = 0;
lat = "41.878114";
long = "-87.629798";
name = "shiv Shankar ";
"status_trip" = 1;
"user_image_url" = "http://app/image/1458129359.userimage";
},
{
"driver_or_rider" = 0;
email = "andrew.payasi#gmail.com";
isGuest = 0;
lat = "43.65322577127058";
long = "-79.38318371772766";
name = username;
"status_trip" = 1;
"user_image_url" = "http://app/image/1456821877.png";
}
)
this is the code in cell for row at index
int randomNumber = indexPath.row % [imageNameArray count];
NSString* nameStr=[goersInfo valueForKey:#"name"];
NSArray * nameStrArray = [nameStr componentsSeparatedByString: #"'s"];
nameStr=[nameStrArray objectAtIndex:0];
NSNumber *indexNumber = self.pinDictionary[nameStr];
index = indexNumber.unsignedIntegerValue;
cell.PinImageView.image=[UIImage imageNamed:[imageNameArray objectAtIndex:index]];
this is dictionary where name are stored
- (void)setupPinDictionary
{
self.pinDictionary = [NSMutableDictionary dictionary];
self.imageNameArray = [[NSArray alloc] initWithObjects:#"pin2#2x.png", #"pin3#2x.png", #"pin4#2x.png", #"pin5#2x.png", #"pin6#2x.png",#"pin8#2x.png",#"pin9#2x.png", nil];
NSUInteger pinImageCount = self.imageNameArray.count;
for (NSDictionary *goersInfo in tableGoersList) {
NSString* nameStr=[goersInfo valueForKey:#"name"];
NSArray * nameStrArray = [nameStr componentsSeparatedByString: #"'s"];
nameStr=[nameStrArray objectAtIndex:0];
if (self.pinDictionary[nameStr] == nil) {
indexPin = arc4random() % pinImageCount;
self.pinDictionary[nameStr] = [NSNumber numberWithUnsignedInteger: indexPin];
}
}
Initially this method is called
-(void)doJourneyGoersList:(id)responseObject{
NSDictionary *dict=[responseObject[#"Count"] firstObject];
checkLocation=[[NSMutableArray alloc]init];
if (dict==nil) {
return;
}
[_messagesButton.badgeButton setBadgeValue:dict[#"Count_Masssage"]];
[_invitesButton.badgeButton setBadgeValue:dict[#"invite_count"]];
[_matchedButton.badgeButton setBadgeValue:dict[#"Count_Match"]];
goersList= [responseObject objectForKey:#"statement"];
CLLocationCoordinate2D orginCllocation=CLLocationCoordinate2DMake([_tripDetails[#"origin_lat"] doubleValue], [_tripDetails[#"origin_long"] doubleValue]);
MKPointAnnotation *annotation =[[MKPointAnnotation alloc] init];
annotation.coordinate=orginCllocation;
[checkLocation addObject:annotation];
tableGoersList=[NSMutableArray new];
for (NSDictionary *dict in goersList) {
NSMutableDictionary *localdict=[NSMutableDictionary new];
loc=[NSMutableDictionary new];
[localdict setObject:[dict objectForKey:#"name"] forKey:#"name"];
[localdict setObject:[dict objectForKey:#"email"] forKey:#"email"];
if ([dict[#"status_trip"] isEqualToString:#"confirm"]) {
[localdict setObject:#"1" forKey:#"status_trip"];
[loc setObject:[dict objectForKey:#"origin_lat"] forKey:#"lat"];
[loc setObject:[dict objectForKey:#"origin_long"] forKey:#"long"];
CLLocationCoordinate2D location=CLLocationCoordinate2DMake([loc[#"lat"] doubleValue], [loc[#"long"] doubleValue]);
[localdict setObject:[dict objectForKey:#"origin_lat"] forKey:#"lat"];
[localdict setObject:[dict objectForKey:#"origin_long"] forKey:#"long"];
if (location.latitude == orginCllocation.latitude && location.longitude == orginCllocation.longitude) {
//location is origin, skip this since it is already added
} else {
MKPointAnnotation *annotation =[[MKPointAnnotation alloc] init];
annotation.coordinate=location;
[checkLocation addObject: annotation];
}
NSLog(#"check location %#",checkLocation);
}
else
[localdict setObject:#"0" forKey:#"status_trip"];
if ([dict[#"isGuest"] isEqualToString:#"1"]) {
[localdict setObject:#"1" forKey:#"isGuest"];
}
else
[localdict setObject:#"0" forKey:#"isGuest"];
[localdict setObject:[dict objectForKey:#"user_image_url"] forKey:#"user_image_url"];
if ([dict[#"driver_or_rider"] isEqualToString:#"Drive"]) {
[localdict setObject:#"1" forKey:#"driver_or_rider"];
[tableGoersList insertObject:localdict atIndex:0];
}
else
{
[localdict setObject:#"0" forKey:#"driver_or_rider"];
[tableGoersList addObject:localdict];
}
//add the objects to the array
}
CLLocationCoordinate2D parkCllocation=CLLocationCoordinate2DMake([_tripDetails[#"park_lat"] doubleValue], [_tripDetails[#"park_long"] doubleValue]);
MKPointAnnotation *jauntAnnotationPark =[[MKPointAnnotation alloc] init];
jauntAnnotationPark.coordinate=parkCllocation;
[checkLocation addObject:jauntAnnotationPark];
[mapView showAnnotations: checkLocation animated:NO];
[mapView setCenterCoordinate:mapView.region.center animated:NO];
int count = [checkLocation count];
CLLocationCoordinate2D coordinateArray[count];
for (int i = 0; i < count; i++) {
coordinateArray[i] = ((MKPointAnnotation *)checkLocation[i]).coordinate;
}
self.routeLine = [MKPolyline polylineWithCoordinates:coordinateArray count:count];
[mapView addOverlay:self.routeLine];
[self setupPinDictionary];
[self.ridersTableView reloadData];
}
and this is the code for view for annotation
{
imageNameArray = [[NSArray alloc] initWithObjects:#"pin2#2x.png", #"pin3#2x.png", #"pin4#2x.png", #"pin5#2x.png", #"pin6#2x.png",#"pin8#2x.png",#"pin9#2x.png",nil];
[self setupPinDictionary];
myAnnotation.image=[UIImage imageNamed:[imageNameArray objectAtIndex:indexPin]];
}
return myAnnotation;
}
I'm using this code to try get directions between two locations. But it outputs co-ordinates using latitude and longitude. But what I want is to get directions for searching based on 2 addresses. How can I get this code to work with addresses?
MKPlacemark *source = [[MKPlacemark alloc]initWithCoordinate:CLLocationCoordinate2DMake(37.776142, -122.424774) addressDictionary:[NSDictionary dictionaryWithObjectsAndKeys:#"",#"", nil] ];
MKMapItem *srcMapItem = [[MKMapItem alloc]initWithPlacemark:source];
[srcMapItem setName:#""];
MKPlacemark *destination = [[MKPlacemark alloc]initWithCoordinate:CLLocationCoordinate2DMake(37.73787, -122.373962) addressDictionary:[NSDictionary dictionaryWithObjectsAndKeys:#"",#"", nil] ];
MKMapItem *distMapItem = [[MKMapItem alloc]initWithPlacemark:destination];
[distMapItem setName:#""];
MKDirectionsRequest *request = [[MKDirectionsRequest alloc]init];
[request setSource:srcMapItem];
[request setDestination:distMapItem];
[request setTransportType:MKDirectionsTransportTypeAny];
MKDirections *direction = [[MKDirections alloc]initWithRequest:request];
[direction calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
NSLog(#"response = %#",response);
NSArray *arrRoutes = [response routes];
[arrRoutes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
MKRoute *rout = obj;
MKPolyline *line = [rout polyline];
[mapview addOverlay:line];
NSLog(#"Rout Name : %#",rout.name);
NSLog(#"Total Distance (in Meters) :%f",rout.distance);
NSArray *steps = [rout steps];
NSLog(#"Total Steps : %lu",(unsigned long)[steps count]);
NSMutableArray *stepsArray=[[NSMutableArray alloc] init];
[steps enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(#"Rout Instruction : %#",[obj instructions]);
NSLog(#"Rout Distance : %f",[obj distance]);
[stepsArray addObject:[obj instructions]];
}];
[self myShowDirections:response];
self.steps.text=[NSString stringWithFormat:#"%#",stepsArray];
First you need to check ios8 in your view didload
locationManager = [[CLLocationManager alloc]init];
locationManager.delegate = self;
// self.map.showsUserLocation=YES;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager setDistanceFilter:kCLDistanceFilterNone];
if([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0){
NSUInteger code = [CLLocationManager authorizationStatus];
if (code == kCLAuthorizationStatusNotDetermined && ([locationManager respondsToSelector:#selector(requestAlwaysAuthorization)] || [locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)])) {
// choose one request according to your business.
if([[NSBundle mainBundle] objectForInfoDictionaryKey:#"NSLocationAlwaysUsageDescription"]){
[locationManager requestAlwaysAuthorization];
} else if([[NSBundle mainBundle] objectForInfoDictionaryKey:#"NSLocationWhenInUseUsageDescription"]) {
[locationManager requestWhenInUseAuthorization];
} else {
NSLog(#"Info.plist does not contain NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription");
}
}
-(void) centerMapForCoordinateArray:(CLLocationCoordinate2D *)routes andCount:(int)count{
MKCoordinateRegion region;
CLLocationDegrees maxLat = -90;
CLLocationDegrees maxLon = -180;
CLLocationDegrees minLat = 90;
CLLocationDegrees minLon = 180;
for(int idx = 0; idx <count; idx++)
{
CLLocationCoordinate2D currentLocations = routes[idx];
if(currentLocations.latitude > maxLat)
maxLat = currentLocations.latitude;
if(currentLocations.latitude < minLat)
minLat = currentLocations.latitude;
if(currentLocations.longitude > maxLon)
maxLon = currentLocations.longitude;
if(currentLocations.longitude < minLon)
minLon = currentLocations.longitude;
}
region.center.latitude = (maxLat + minLat) / 2;
region.center.longitude = (maxLon + minLon) / 2;
region.span.latitudeDelta = maxLat - minLat;
region.span.longitudeDelta = maxLon - minLon;
[self.map setRegion:region animated:YES];
}
- (MKPolyline *)polylineWithEncodedString:(NSString *)encodedString {
const char *bytes = [encodedString UTF8String];
NSUInteger length = [encodedString lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
NSUInteger idx = 0;
NSUInteger count = length / 4;
CLLocationCoordinate2D *coords = calloc(count, sizeof(CLLocationCoordinate2D));
NSUInteger coordIdx = 0;
float latitude = 0;
float longitude = 0;
while (idx < length) {
char byte = 0;
int res = 0;
char shift = 0;
do {
byte = bytes[idx++] - 63;
res |= (byte & 0x1F) << shift;
shift += 5;
} while (byte >= 0x20);
float deltaLat = ((res & 1) ? ~(res >> 1) : (res >> 1));
latitude += deltaLat;
shift = 0;
res = 0;
do {
byte = bytes[idx++] - 0x3F;
res |= (byte & 0x1F) << shift;
shift += 5;
} while (byte >= 0x20);
float deltaLon = ((res & 1) ? ~(res >> 1) : (res >> 1));
longitude += deltaLon;
float finalLat = latitude * 1E-5;
float finalLon = longitude * 1E-5;
CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(finalLat, finalLon);
coords[coordIdx++] = coord;
if (coordIdx == count) {
NSUInteger newCount = count + 10;
coords = realloc(coords, newCount * sizeof(CLLocationCoordinate2D));
count = newCount;
}
}
MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords count:coordIdx];
free(coords);
return polyline;
}
- (void)getDirections {
CLLocation *newLocation = [[CLLocation alloc] initWithLatitude:currentLocation.coordinate.latitude longitude:currentLocation.coordinate.longitude];
MKPointAnnotation *provider = [[MKPointAnnotation alloc] init];
provider.coordinate = CLLocationCoordinate2DMake(newLocation.coordinate.latitude, newLocation.coordinate.longitude);
provider.title = [self getAddress];
[self.map addAnnotation:provider];
// 13.069166 80.191388
CLLocationCoordinate2D location;
// location.latitude =12.982672000000000000; // change to your coordinate latitude
// location.longitude =80.263380999999980000;
location.latitude =[self.Latitude doubleValue]; // change to your coordinate latitude
location.longitude =[self.Longtitude doubleValue];
CLLocation *keyPlace = [[CLLocation alloc] initWithLatitude:location.latitude longitude:location.longitude];
MKPointAnnotation *user = [[MKPointAnnotation alloc] init];
user.coordinate = CLLocationCoordinate2DMake(keyPlace.coordinate.latitude, keyPlace.coordinate.longitude);
NSString *add=[NSString stringWithFormat:#"%f %f",location.latitude,location.longitude];
NSString *tit=[self getAddressFromLatLong:add];
user.title=tit;
[self.map addAnnotation:user];
CLLocationCoordinate2D endCoordinate;
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/directions/json?origin=%f,%f&destination=%f,%f&sensor=false&mode=driving", newLocation.coordinate.latitude, newLocation.coordinate.longitude, keyPlace.coordinate.latitude, keyPlace.coordinate.longitude]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (!error) {
NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:&error];
if ([[responseDict valueForKey:#"status"] isEqualToString:#"ZERO_RESULTS"]) {
[[[UIAlertView alloc] initWithTitle:#"Error"
message:#"Could not route path from your current location"
delegate:nil
cancelButtonTitle:#"Close"
otherButtonTitles:nil, nil] show];
return;
}
int points_count = 0;
if ([[responseDict objectForKey:#"routes"] count])
points_count = (int)[[[[[[responseDict objectForKey:#"routes"] objectAtIndex:0] objectForKey:#"legs"] objectAtIndex:0] objectForKey:#"steps"] count];
if (!points_count) {
[[[UIAlertView alloc] initWithTitle:#"Error"
message:#"Could not route path from your current location"
delegate:nil
cancelButtonTitle:#"Close"
otherButtonTitles:nil, nil] show];
return;
}
CLLocationCoordinate2D points[points_count];
NSLog(#"routes %#", [[[[responseDict objectForKey:#"routes"] objectAtIndex:0]objectForKey:#"overview_polyline"] objectForKey:#"points"]
);
MKPolyline *polyline = [self polylineWithEncodedString:[[[[responseDict objectForKey:#"routes"] objectAtIndex:0]objectForKey:#"overview_polyline"] objectForKey:#"points"]];
[self.map addOverlay:polyline];
int j = 0;
NSArray *steps = nil;
if (points_count && [[[[responseDict objectForKey:#"routes"] objectAtIndex:0] objectForKey:#"legs"] count])
steps = [[[[[responseDict objectForKey:#"routes"] objectAtIndex:0] objectForKey:#"legs"] objectAtIndex:0] objectForKey:#"steps"];
for (int i = 0; i < points_count; i++) {
double st_lat = [[[[steps objectAtIndex:i] objectForKey:#"start_location"] valueForKey:#"lat"] doubleValue];
double st_lon = [[[[steps objectAtIndex:i] objectForKey:#"start_location"] valueForKey:#"lng"] doubleValue];
//NSLog(#"lat lon: %f %f", st_lat, st_lon);
if (st_lat > 0.0f && st_lon > 0.0f) {
points[j] = CLLocationCoordinate2DMake(st_lat, st_lon);
j++;
}
double end_lat = [[[[steps objectAtIndex:i] objectForKey:#"end_location"] valueForKey:#"lat"] doubleValue];
double end_lon = [[[[steps objectAtIndex:i] objectForKey:#"end_location"] valueForKey:#"lng"] doubleValue];
//NSLog(#"lat %f lng %f",end_lat,end_lon);
//if (end_lat > 0.0f && end_lon > 0.0f) {
points[j] = CLLocationCoordinate2DMake(end_lat, end_lon);
endCoordinate = CLLocationCoordinate2DMake(end_lat, end_lon);
j++;
//}
}
NSLog(#"points Count %d",points_count);
// MKPolyline *polyline = [MKPolyline polylineWithCoordinates:points count:points_count];
// [self.mapView addOverlay:polyline];
[self centerMapForCoordinateArray:points andCount:points_count];
}
}
- (MKPolylineRenderer *)mapView:(MKMapView *)mapView
viewForOverlay:(id<MKOverlay>)overlay {
MKPolylineRenderer *polylineView = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
polylineView.lineWidth = 3;
polylineView.strokeColor = [[UIColor alloc] initWithRed:5.0/255 green:102.0/255 blue:48.0/255 alpha:1];
return polylineView;
}
EDIT:
-(void)showRoute:(MKDirectionsResponse *)response
{
for (MKRoute *route in response.routes){
[mapView addOverlay:route.polyline level:MKOverlayLevelAboveRoads];
}
}
-(void)getPathDirections:(CLLocationCoordinate2D)source withDestination:(CLLocationCoordinate2D)destination{
MKPlacemark *placemarkSrc = [[MKPlacemark alloc] initWithCoordinate:source addressDictionary:nil];
MKMapItem *mapItemSrc = [[MKMapItem alloc] initWithPlacemark:placemarkSrc];
MKPlacemark *placemarkDest = [[MKPlacemark alloc] initWithCoordinate:destination addressDictionary:nil];
MKMapItem *mapItemDest = [[MKMapItem alloc] initWithPlacemark:placemarkDest];
[mapItemSrc setName:#"name1"];
[mapItemDest setName:#"name2"];
MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
[request setSource:mapItemSrc];
[request setDestination:mapItemDest];
[request setTransportType:MKDirectionsTransportTypeAutomobile];
request.requestsAlternateRoutes = NO;
MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
[directions calculateDirectionsWithCompletionHandler:
^(MKDirectionsResponse *response, NSError *error) {
if (error) {
// Handle Error
// UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"ShareMyTable" message:#"Root Map not available to your location." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
// [alert show];
} else {
[mapView removeOverlays:mapView.overlays];
[self showRoute:response];
}
}];
}
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
{
// 41,142,175
if ([overlay isKindOfClass:[MKPolyline class]]) {
MKPolyline *route = (MKPolyline *)overlay;
MKPolylineRenderer *routeRenderer = [[MKPolylineRenderer alloc] initWithPolyline:route];
routeRenderer.strokeColor = [UIColor colorWithRed:(41/255.0) green:(142/255.0) blue:(175/255.0) alpha:0.6f];
routeRenderer.lineWidth = 2.5;
return routeRenderer;
}
else return nil;
}
you can read about supported country list
link
When you find any rout between two places,than always use different source and destination place.
In your code you use same latitude and longitude so MKDirections have no Rout to make direction.
So in Your code use different Lat. and Long.
Like...
KPlacemark *source = [[MKPlacemark alloc]initWithCoordinate:CLLocationCoordinate2DMake(37.776142, -122.424774) addressDictionary:[NSDictionary dictionaryWithObjectsAndKeys:#"",#"", nil] ];
MKMapItem *srcMapItem = [[MKMapItem alloc]initWithPlacemark:source];
[srcMapItem setName:#""];
MKPlacemark *destination=[[MKPlacemarkalloc]initWithCoordinate:CLLocationCoordinate2DMake(40.73787, -142.373962) addressDictionary:[NSDictionary dictionaryWithObjectsAndKeys:#"",#"", nil] ];
After use this Latitude and Longitude you can draw your rout any two places.
I hope my answer is helpful for you.
I am working on an application where i want path between two locations.
I implemented some code. This is fine for short distance path but when i creating path for long distance like From Jaipur, Rajasthan, India to Jorhat, Aasam, India, my application get crashed.
This is my code
-(void)findPath{
[rectangle setMap:nil];
NSString* str = [NSMutableString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%#&destination=%#&sensor=true", self.FromSearch, self.toSearch];
if (_travelMode==UICGTravelModeWalking) {
str=[str stringByAppendingFormat:#"&mode=walking"];
}
NSURL *url=[[NSURL alloc]initWithString:[str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSArray* latestRoutes = [json objectForKey:#"routes"];
NSString *points=[[[latestRoutes objectAtIndex:0] objectForKey:#"overview_polyline"] objectForKey:#"points"];
if ([latestRoutes isKindOfClass:[NSArray class]]&&latestRoutes.count==0) {
UIAlertView *alrt=[[UIAlertView alloc]initWithTitle:#"Alert" message:#"didn't find direction" delegate:nil cancelButtonTitle:#"ok" otherButtonTitles:nil, nil];
[alrt show];
return;
}
arrDistance =[[[json valueForKeyPath:#"routes.legs.steps.distance.text"] objectAtIndex:0]objectAtIndex:0];
totalDuration = [[[json valueForKeyPath:#"routes.legs.duration.text"] objectAtIndex:0]objectAtIndex:0];
totalDistance = [[[json valueForKeyPath:#"routes.legs.distance.text"] objectAtIndex:0]objectAtIndex:0];
arrDescription =[[[json valueForKeyPath:#"routes.legs.steps.html_instructions"] objectAtIndex:0] objectAtIndex:0];
dictRouteInfo=[NSDictionary dictionaryWithObjectsAndKeys:totalDistance,#"totalDistance",totalDuration,#"totalDuration",arrDistance ,#"distance",arrDescription,#"description", nil];
double srcLat=[[[[json valueForKeyPath:#"routes.legs.start_location.lat"] objectAtIndex:0] objectAtIndex:0] doubleValue];
double srcLong=[[[[json valueForKeyPath:#"routes.legs.start_location.lng"] objectAtIndex:0] objectAtIndex:0] doubleValue];
totalLat = [[NSMutableArray alloc]init];
totalLong = [[NSMutableArray alloc]init];
//for (int i = 0; i<arrDistance.count; i++) {
totalLat = [[[json valueForKeyPath:#"routes.legs.steps.start_location.lat"] objectAtIndex:0] objectAtIndex:0];
totalLong = [[[json valueForKeyPath:#"routes.legs.steps.start_location.lng"] objectAtIndex:0] objectAtIndex:0];
[self saveInfoForPath];
// }
CLLocationCoordinate2D location;
location.latitude = srcLat;
location.longitude = srcLong;
// mapView.camera = [GMSCameraPosition cameraWithTarget:location
// zoom:10];
//GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc]initWithPath:<#(GMSPath *)#>]
// [[GMSCoordinateBounds alloc] initWithCoordinate:vancouver coordinate:calgary];
#try {
// TODO: better parsing. Regular expression?
NSArray *temp= [self decodePolyLine:[points mutableCopy]];
GMSMutablePath *path = [GMSMutablePath path];
for(int idx = 0; idx < [temp count]; idx++)
{
CLLocation *location=[temp objectAtIndex:idx];
[path addCoordinate:location.coordinate];
}
// create the polyline based on the array of points.
rectangle = [GMSPolyline polylineWithPath:path];
rectangle.strokeWidth=5.0;
rectangle.map = mapView;
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc]initWithPath:path];
[mapView moveCamera:[GMSCameraUpdate fitBounds:bounds]];
}
#catch (NSException * e) {
// TODO: show error
}
}
decodePolyline() method coding
-(NSMutableArray *)decodePolyLine: (NSMutableString *)encoded {
[encoded replaceOccurrencesOfString:#"\\\\" withString:#"\\"
options:NSLiteralSearch
range:NSMakeRange(0, [encoded length])];
NSInteger len = [encoded length];
NSInteger index = 0;
NSMutableArray *array = [[NSMutableArray alloc] init] ;
NSInteger lat=0;
NSInteger lng=0;
while (index < len) {
NSInteger b;
NSInteger shift = 0;
NSInteger result = 0;
do {
b = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
NSInteger dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
NSInteger dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
lng += dlng;
NSNumber *latitude = [[NSNumber alloc] initWithFloat:lat * 1e-5] ;
NSNumber *longitude = [[NSNumber alloc] initWithFloat:lng * 1e-5] ;
printf("[%f,", [latitude doubleValue]);
printf("%f]", [longitude doubleValue]);
CLLocation *loc = [[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]] ;
[array addObject:loc];
}
return array;
}
What should i do. Please suggest.
You can try pathFromEncodedPath method in place of decodePolyLine for getting path from encodeString.
NSString *points=[[[latestRoutes objectAtIndex:0] objectForKey:#"overview_polyline"] objectForKey:#"points"];
polyline = [GMSPolyline polylineWithPath: [GMSPath pathFromEncodedPath: points]];
polyline.map = mapView;
polyline.strokeColor = [UIColor colorWithRed:0/255.0 green:4/255.0 blue:255/255.0 alpha:1.0];
polyline.strokeWidth = 4.0f;
I am getting a GMSPolyline to custom location but I am not getting a route direction (GMSPolyline) from user location to some custom location.
What I have done is placed a GMSMapView and kept core location. I am updating the route in core location delegate method (locationManager: didUpdateLocations:).
I want to use Google Maps for iOS SDK since Apple Maps don't have directions in the country I need. My code is below:
- (void)viewDidLoad
{
[super viewDidLoad];
waypointStrings_ = [[NSMutableArray alloc]init];
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:self.latitude longitude:self.longitude zoom:13];
mapView_ = [GMSMapView mapWithFrame:CGRectZero camera:camera];
mapView_.myLocationEnabled = YES;
self.view = mapView_;
CLLocationManager *locManager = [[CLLocationManager alloc] init];
if ( [CLLocationManager locationServicesEnabled] ) {
[locManager setDelegate:self];
[locManager setDesiredAccuracy:kCLLocationAccuracyBest];
[locManager startUpdatingLocation];
}
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocationCoordinate2D userCoordinate = [[locations lastObject] coordinate];
GMSMarker *marker = [GMSMarker markerWithPosition:CLLocationCoordinate2DMake(self.latitude,self.longitude)];
marker.map = mapView_;
NSString *majlisPositionString = [[NSString alloc] initWithFormat:#"%f,%f", self.latitude,self.longitude];
[waypointStrings_ addObject:majlisPositionString];
GMSMarker *userMarker = [GMSMarker markerWithPosition:CLLocationCoordinate2DMake(userCoordinate.latitude, userCoordinate.longitude)];
userMarker.map = mapView_;
NSString *userPositionString = [[NSString alloc] initWithFormat:#"%f,%f", userCoordinate.latitude, userCoordinate.longitude];
[waypointStrings_ addObject:userPositionString];
NSString *sensor = #"false";
NSArray *parameters = [NSArray arrayWithObjects:sensor, waypointStrings_, nil];
NSArray *keys = [NSArray arrayWithObjects:#"sensor", #"waypoints", nil];
NSDictionary *query = [NSDictionary dictionaryWithObjects:parameters forKeys:keys];
MDDirectionService *mds=[[MDDirectionService alloc] init];
SEL selector = #selector(addDirections:);
[mds setDirectionsQuery:query withSelector:selector withDelegate:self];
}
- (void)addDirections:(NSDictionary *)json {
NSDictionary *routes = [json objectForKey:#"routes"][0];
NSDictionary *route = [routes objectForKey:#"overview_polyline"];
NSString *overview_route = [route objectForKey:#"points"];
GMSPath *path = [GMSPath pathFromEncodedPath:overview_route];
GMSPolyline *polyline = [GMSPolyline polylineWithPath:path];
polyline.map = mapView_;
}
-(void)LoadMapRoute:(NSString*)SourceAddress andDestinationAddress:(NSString*)DestinationAdds
{
NSString *strUrl;
strUrl= [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%#&destination=%#&sensor=false",SourceAddress,DestinationAdds];
strUrl=[strUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSData *data =[NSData dataWithContentsOfURL:[NSURL URLWithString:strUrl]];
NSError* error;
if (data) {
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:data //1
options:kNilOptions
error:&error];
NSArray *arrRouts=[json objectForKey:#"routes"];
if ([arrRouts isKindOfClass:[NSArray class]]&&arrRouts.count==0) {
[self zoomToFitMapAnnotations:self.mapView];
return;
}
CLLocationCoordinate2D coordinates[2];
coordinates[0].latitude = [[CommonUtils checkNullString:[AppDelegate getAppDelegate].strLatitude] doubleValue];Current loaction latitude.
coordinates[0].longitude = [[CommonUtils checkNullString:[AppDelegate getAppDelegate].strLongitude] doubleValue];//Current loaction longitude.
coordinates[1].latitude = [[CommonUtils checkNullString:latitute] doubleValue];
coordinates[1].longitude = [[CommonUtils checkNullString:longitude] doubleValue];
if (CLLocationCoordinate2DIsValid(coordinates[1]) && CLLocationCoordinate2DIsValid(coordinates[0]))
{
//NSLog(#"Coordinate valid");
self.mapView.delegate=self;
CLLocation *location1 = [[CLLocation alloc] initWithLatitude:coordinates[0].latitude longitude:coordinates[0].longitude];
CLLocation *location2 = [[CLLocation alloc] initWithLatitude:coordinates[1].latitude longitude:coordinates[1].longitude];
CLLocationDistance kilometers = [location1 distanceFromLocation:location2] / 1000;
//NSLog(#"%f",kilometers);
self.lblRideViewkilometer.text=[NSString stringWithFormat:#"%f KM",kilometers];
// //NSLog(#"Distance i meters: %f", [location1 distanceFromLocation:location2]);
// self.polyline = [MKPolyline polylineWithCoordinates:coordinates count:2];
// [self.mapView setVisibleMapRect:[self.polyline boundingMapRect]];
//
//
// //If you want the route to be visible
// [self.mapView addOverlay:self.polyline];
} else {
//NSLog(#"Coordinate invalid");
}
NSArray* arrpolyline = [[[json valueForKeyPath:#"routes.legs.steps.polyline.points"] objectAtIndex:0] objectAtIndex:0]; //2
double srcLat=[[[[json valueForKeyPath:#"routes.legs.start_location.lat"] objectAtIndex:0] objectAtIndex:0] doubleValue];
double srcLong=[[[[json valueForKeyPath:#"routes.legs.start_location.lng"] objectAtIndex:0] objectAtIndex:0] doubleValue];
double destLat=[[[[json valueForKeyPath:#"routes.legs.end_location.lat"] objectAtIndex:0] objectAtIndex:0] doubleValue];
double destLong=[[[[json valueForKeyPath:#"routes.legs.end_location.lng"] objectAtIndex:0] objectAtIndex:0] doubleValue];
CLLocationCoordinate2D sourceCordinate = CLLocationCoordinate2DMake(srcLat, srcLong);
CLLocationCoordinate2D destCordinate = CLLocationCoordinate2DMake(destLat, destLong);
[self addAnnotationSrcAndDestination:sourceCordinate :destCordinate andAdds:nil andDestinationAddress:DestinationAdds];
// NSArray *steps=[[aary objectAtIndex:0]valueForKey:#"steps"];
// replace lines with this may work
polyLinesArray =[[NSMutableArray alloc]initWithCapacity:0];
for (int i = 0; i < [arrpolyline count]; i++)
{
NSString* encodedPoints = [arrpolyline objectAtIndex:i] ;
MKPolyline *route = [self polylineWithEncodedString:encodedPoints];
[polyLinesArray addObject:route];
}
self.polyline = [MKPolyline polylineWithCoordinates:coordinates count:2];
[self.mapView setVisibleMapRect:[self.polyline boundingMapRect]];
[self.mapView addOverlays:polyLinesArray];
self.mapView.delegate = self;
[self zoomToFitMapAnnotations:self.mapView];
}else{
// [self.btnDirection setEnabled:NO];
// [self ShowAlert:#"didn't find direction"];
}
}-(void)addAnnotationSrcAndDestination :(CLLocationCoordinate2D )srcCord :(CLLocationCoordinate2D)destCord andAdds:(NSString*)SourceAddress andDestinationAddress:(NSString*)DestinationAdds
{
MKPointAnnotation *sourceAnnotation = [[MKPointAnnotation alloc]init];
destAnnotation = [[MKPointAnnotation alloc]init];
sourceAnnotation.coordinate=srcCord;
destAnnotation.coordinate=destCord;
sourceAnnotation.title=SourceAddress;
CLLocation *LocationAtual = [[CLLocation alloc] initWithLatitude:destCord.latitude longitude:destCord.longitude];
CLGeocoder *geocoder = [[CLGeocoder alloc] init] ;
[geocoder reverseGeocodeLocation:LocationAtual
completionHandler:^(NSArray *placemarks, NSError *error)
{
if (error){
//NSLog(#"Geocode failed with error: %#", error);
return;
}
CLPlacemark *placemark = [placemarks objectAtIndex:0];
//NSLog(#"placemark.ISOcountryCode %#",placemark.ISOcountryCode);
//NSLog(#"locality %#",placemark.subLocality);
//NSLog(#"postalCode %#",placemark.postalCode);
destAnnotation.title=[NSString stringWithFormat:#"%# %# ",placemark.name,placemark.locality];
// [self.mapView.userLocation setTitle:[NSString stringWithFormat:#"%# %# ",placemark.name,placemark.locality]];
}];
// destAnnotation.title=DestinationAdds;
//destAnnotation.title=[NSString stringWithFormat:#"%#,%#,%#",[self.dictRetailerInfo objectForKey:#"street_address1"],[self.dictRetailerInfo objectForKey:#"city"],[self.dictRetailerInfo objectForKey:#"country"]];
// destAnnotation.title=nil;
[self.mapView addAnnotation:sourceAnnotation];
[self.mapView addAnnotation:destAnnotation];
}
- (MKPolyline *)polylineWithEncodedString:(NSString *)encodedString {
const char *bytes = [encodedString UTF8String];
NSUInteger length = [encodedString lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
NSUInteger idx = 0;
NSUInteger count = length / 4;
CLLocationCoordinate2D *coords = calloc(count, sizeof(CLLocationCoordinate2D));
NSUInteger coordIdx = 0;
float latitude = 0;
float longitude = 0;
while (idx < length) {
char byte = 0;
int res = 0;
char shift = 0;
do {
byte = bytes[idx++] - 63;
res |= (byte & 0x1F) << shift;
shift += 5;
} while (byte >= 0x20);
float deltaLat = ((res & 1) ? ~(res >> 1) : (res >> 1));
latitude += deltaLat;
shift = 0;
res = 0;
do {
byte = bytes[idx++] - 0x3F;
res |= (byte & 0x1F) << shift;
shift += 5;
} while (byte >= 0x20);
float deltaLon = ((res & 1) ? ~(res >> 1) : (res >> 1));
longitude += deltaLon;
float finalLat = latitude * 1E-5;
float finalLon = longitude * 1E-5;
CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(finalLat, finalLon);
coords[coordIdx++] = coord;
if (coordIdx == count) {
NSUInteger newCount = count + 10;
coords = realloc(coords, newCount * sizeof(CLLocationCoordinate2D));
count = newCount;
}
}
MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords count:coordIdx];
free(coords);
return polyline;
}
-(void)zoomToFitMapAnnotations:(MKMapView*)aMapView
{
if([aMapView.annotations count] == 0)
return;
CLLocationCoordinate2D topLeftCoord;
topLeftCoord.latitude = -90;
topLeftCoord.longitude = 180;
CLLocationCoordinate2D bottomRightCoord;
bottomRightCoord.latitude = 90;
bottomRightCoord.longitude = -180;
for(MKPointAnnotation *annotation in self.mapView.annotations)
{
if (![[annotation class] isEqual:[MKUserLocation class]]) {
topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude);
topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude);
bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude);
bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude);
}
}
MKCoordinateRegion region;
region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5;
region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5;
region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1; // Add a little extra space on the sides
region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.1; // Add a little extra space on the sides
region = [aMapView regionThatFits:region];
[self.mapView setRegion:region animated:YES];
mapZoom=YES;
}
//- (void)mapView:(MKMapView *)mv didAddAnnotationViews:(NSArray *)views
//{
// MKMapRect zoomRect = MKMapRectNull;
// for (id <MKAnnotation> annotation in mv.annotations)
// {
// MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
// MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
// zoomRect = MKMapRectUnion(zoomRect, pointRect);
// }
// [mv setVisibleMapRect:zoomRect animated:YES];
//}
- (void)moveMapToLocation:(CLLocation*)tmpLocation {
CLLocationDistance visibleDistance = 1000; // 1 kilometers
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(tmpLocation.coordinate, visibleDistance, visibleDistance);
MKCoordinateRegion adjustedRegion = [self.mapView regionThatFits:viewRegion];
[self.mapView setRegion:adjustedRegion animated:YES];
}
var arrayPolyline = [GMSPolyline]()
var selectedRought:String!
func LoadMapRoute1()
{
let strUrl:String = "https://maps.googleapis.com/maps/api/directions/json?sensor=false&mode=driving&alternatives=true&origin=\(self.source.latitude),\(self.source.longitude)&destination=\(self.destination.latitude),\(self.destination.longitude)"
let escapedString = strUrl.replacingOccurrences(of: " ", with: "")
let url = URL(string: escapedString)
URLSession.shared.dataTask(with: url!, completionHandler:
{
(data, response, error) in
if(error != nil)
{
print("error")
}
else
{
do{
let json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String : AnyObject]
let arrRouts = json["routes"] as! NSArray
for polyline in self.arrayPolyline
{
polyline.map = nil;
}
self.arrayPolyline.removeAll()
let pathForRought:GMSMutablePath = GMSMutablePath()
if (arrRouts.count == 0)
{
let distance:CLLocationDistance = CLLocation.init(latitude: self.source.latitude, longitude: self.source.longitude).distance(from: CLLocation.init(latitude: self.destination.latitude, longitude: self.destination.longitude))
pathForRought.add(self.source)
pathForRought.add(self.destination)
let polyline = GMSPolyline.init(path: pathForRought)
polyline.strokeWidth = 5
polyline.strokeColor = UIColor.blue
polyline.isTappable = true
self.arrayPolyline.append(polyline)
if (distance > 8000000)
{
polyline.geodesic = false
}
else
{
polyline.geodesic = true
}
polyline.map = self.mapView;
}
else
{
for (index, element) in arrRouts.enumerated()
{
let dicData:NSDictionary = element as! NSDictionary
let routeOverviewPolyline = dicData["overview_polyline"] as! NSDictionary
let path = GMSPath.init(fromEncodedPath: routeOverviewPolyline["points"] as! String)
let polyline = GMSPolyline.init(path: path)
polyline.isTappable = true
self.arrayPolyline.append(polyline)
polyline.strokeWidth = 5
if index == 0
{
polyline.strokeColor = UIColor.blue;
}
else
{
polyline.strokeColor = UIColor.darkGray;
}
polyline.geodesic = true;
}
for po in self.arrayPolyline.reversed()
{
po.map = self.mapView;
}
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5)
{
let bounds:GMSCoordinateBounds = GMSCoordinateBounds.init(path: GMSPath.init(fromEncodedPath: self.selectedRought)!)
self.mapView.animate(with: GMSCameraUpdate.fit(bounds))
}
}
catch let error as NSError
{
print("error:\(error)")
}
}
}).resume()
}