Xcode IOS how to implement Getfeatureinfo of WMS in IOS - ios

I am using WMSOnGooglemaps sdk for base maps . I can see my layers from geoserver overlayed on google maps but I am stuck at getfeatureinfo request(I want information of layer on click of layer).I am geeting the info on click of layer but it is wrong.
//Code to display layer
- (void)loadView
{
GMSTileURLConstructor urls1 = ^(NSUInteger x, NSUInteger y, NSUInteger z)
{
bbox = bboxFromXYZ(x,y,z);
NSString *urlKN1 = [NSString stringWithFormat:#"http://IPADDRESS/geoserver/wms?service=WMS&version=1.1.1&request=GetMap&layers=gidc:plots_category_wise&bbox=%f,%f,%f,%f&width=768&height=1024&srs=EPSG:900913&format=image/png&transparent=true",
bbox.left, bbox.bottom,bbox.right,bbox.top];
return [NSURL URLWithString:urlKN1];
};
GMSTileLayer *tileLayer1 = [GMSURLTileLayer tileLayerWithURLConstructor:urls1];
tileLayer1.map = mapView;
}
- (void)mapView:(GMSMapView *)mapView1 didTapAtCoordinate:(CLLocationCoordinate2D)coordinate
{
CLLocationCoordinate2D position = CLLocationCoordinate2DMake(coordinate.latitude,coordinate.longitude);
NSLog(#"Latitude= %f lonitude = %f",coordinate.latitude,coordinate.longitude);
GMSMarker *marker = [GMSMarker markerWithPosition:position];
point = [mapView1.projection pointForCoordinate:marker.position];
//ankita.dutta#hardcastlegis.com
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc]initWithCoordinate:coordinate coordinate:coordinate];
NSLog(#"Bounds.minx = %f,%f,%f,%f",bounds.southWest.longitude,bounds.northEast.latitude,bounds.northEast.longitude,bounds.southWest.latitude);
NSLog(#"Pointer: %d, %d",[[NSNumber numberWithFloat:point.x] intValue],[[NSNumber numberWithFloat:point.y] intValue] );
GMSVisibleRegion region;
region = mapView.projection.visibleRegion;
GMSCoordinateBounds *bounds1 = [[GMSCoordinateBounds alloc] initWithRegion:region];
NSLog(#"Bounds.minx = %.15f,%.15f,%.15f,%.15f",bounds1.southWest.longitude,bounds1.northEast.latitude,bounds1.northEast.longitude,bounds1.southWest.latitude);
[self getInfo:[[NSNumber numberWithFloat:point.x] intValue] :[[NSNumber numberWithFloat:point.y] intValue] :bounds1.southWest.longitude :bounds1.northEast.latitude :bounds1.northEast.longitude :bounds1.southWest.latitude];
}
-(void)getInfo : (int) xValue : (int) yValue :(double)bboxLMin :(double)bboxLMax :(double)bboxRMin :(double)bboxTMax
{
// [self showLoadingView:YES];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
{
NSMutableURLRequest * request=[[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://117.239.80.70:8282/geoserver/wms?service=WMS&version=1.1.1&srs=EPSG:4326&bbox=%.15f,%.15f,%.15f,%.15f&styles=&&buffer=40&info_format=application/json&request=GetFeatureInfo&layers=gidc:plots_category_wise&query_layers=gidc:plots_category_wise&width=%d&height=%d&x=%d&y=%d",bboxLMin,bboxLMax,bboxRMin,bboxTMax, [[NSNumber numberWithFloat:mapView.frame.size.width] intValue],[[NSNumber numberWithFloat:mapView.frame.size.height] intValue],xValue,yValue]]];
NSURLSession * session =[NSURLSession sharedSession];
[[session dataTaskWithRequest:request completionHandler:^(NSData * data, NSURLResponse * response, NSError * error)
{
if (data!=NULL)
{
dispatch_async(dispatch_get_main_queue(), ^
{
//[self showLoadingView:NO];
NSMutableDictionary *listDict=[NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"Responce =%#",listDict);
NSMutableArray *dataArr = [[listDict valueForKey:#"features"]valueForKey:#"properties"];
[self response:dataArr];
});
}
}]resume];
});
}

Related

How to iterate over the path from Google Directions API?

I am trying to move the marker along two selected markers with their coordinates set.
I am getting the path from this code:
GMSPath *path1 =[GMSPath pathFromEncodedPath:self.dataReceive[#"routes"][0][#"overview_polyline"][#"points"]];
When i am using the for loop to move first marker to the position of second marker. It is taking a straight path but it should move along the path coordinates that has been fetched from the google directions API.
for (int i = 0; i< path1.count; i++) {
CLLocationCoordinate2D position = [path1 coordinateAtIndex:i];
[CATransaction begin];
[CATransaction setAnimationDuration:50];
self.marker.position = position;
self.marker.map = self.mapView;
[CATransaction commit];
}
Thanks.
Try this code Objective C.
- (void)showPathFromCurrentLocationForCoordinate:(CLLocationCoordinate2D)coord{
CLLocationCoordinate2D destination = coord;
NSMutableString *urlString = [[NSMutableString alloc] initWithString:#"https://maps.googleapis.com/maps/api/directions/json?"];
[urlString appendString:[NSString stringWithFormat:#"origin=%f,%f&destination=%f,%f&sensor=true",self.deviceLocation.latitude,self.deviceLocation.longitude,destination.latitude,destination.longitude]];
[RestApi getPath:urlString withParameter:nil withHandler:^(id responseObject, NSError *error, NSURLResponse *response) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error == nil) {
NSDictionary *json = responseObject;
NSArray *routes = [json objectForKey:#"routes"];
if (routes != nil && routes.count > 0) {
NSDictionary *route = [routes objectAtIndex:0];
long distance = 0;
NSArray *legs = [route objectForKey:#"legs"];
for (NSDictionary *leg in legs) {
long dist = [leg[#"distance"][#"value"] longValue];
distance = distance + dist;
}
GMSPath *path =[GMSPath pathFromEncodedPath:route[#"overview_polyline"][#"points"]];
GMSPolyline *line = [GMSPolyline polylineWithPath:path];
line.strokeColor = PATH_STROKE_COLOR;
line.strokeWidth = PATH_STROKE_WIDTH;
line.map = mapView;
GMSMutablePath *markerpath = [GMSMutablePath path];
[markerpath addCoordinate: self.deviceLocation];
[markerpath addCoordinate: marker.position];
GMSCoordinateBounds *bonds = [[GMSCoordinateBounds alloc] initWithPath:markerpath];
[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithFloat: 1.0] forKey:kCATransactionAnimationDuration];
[mapView animateWithCameraUpdate:[GMSCameraUpdate fitBounds:bonds withPadding:MAP_BOUNDS_OFFSET_PADDING]];
[CATransaction commit];
}
else{
NSLog(#"Google direction API failed.");
}
}
else if (error != nil){
NSLog(#"%#",error.localizedDescription);
}
});
}];
}

iOS Multiple Polyline Overlay causes memory issue

I’m using mkmapview in my application it contains multiple polyline overlay and multiple custom annotations, while running the application receiving memory warning oftenly, I struggled a lot
Thanks in advance.
for (int i = 0; i<[latArray count]-1; i++)
{
NSString *lat1 = [latArray objectAtIndex:i];
NSString *longi1 = [longArray objectAtIndex:i];
firstPlace = CLLocationCoordinate2DMake([lat1 doubleValue], [longi1 doubleValue]);
NSString *lat2 = [latArray objectAtIndex:i+1];
NSString *longi2 = [longArray objectAtIndex:i+1];
secPlace = CLLocationCoordinate2DMake([lat2 doubleValue], [longi2 doubleValue]);
[self directionRequest:firstPlace :secPlace index:i];
}
-(void)directionRequest:(CLLocationCoordinate2D )firstCord :(CLLocationCoordinate2D )secCord index:(int)index
{
#try
{
MKPlacemark *source=[[MKPlacemark alloc]initWithCoordinate:firstCord addressDictionary:[NSDictionary dictionaryWithObjectsAndKeys:#"",#"", nil]];
MKMapItem *sourceMapItem=[[MKMapItem alloc]initWithPlacemark:source];
[sourceMapItem setName:#""];
MKPlacemark *destination=[[MKPlacemark alloc]initWithCoordinate:secCord addressDictionary:[NSDictionary dictionaryWithObjectsAndKeys:#"",#"", nil]];
MKMapItem *destinationMapitem=[[MKMapItem alloc]initWithPlacemark:destination];
[destinationMapitem setName:#""];
MKDirectionsRequest *dirRequest=[[MKDirectionsRequest alloc]init];
[dirRequest setSource:sourceMapItem];
[dirRequest setDestination:destinationMapitem];
// dirRequest.requestsAlternateRoutes = YES;
[dirRequest setTransportType:MKDirectionsTransportTypeAutomobile];
MKDirections *direction=[[MKDirections alloc]initWithRequest:dirRequest];
[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];
[iMapView addOverlay:line];
}];
}];
}
#catch (NSException *exception)
{
}
}

Parsing JSON to place annotations on Map

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];
}

Multiple route between two location in iPhone

I need to show multiple routes in my iOS application that uses Maps API.
I am able to draw single route but how I can draw multiple routes?
I am using google direction api to get single route
http://maps.googleapis.com/maps/api/directions/json?origin=28.6353080000,77.2249600000&destination=28.5355161000,77.3910265000&mode=walking&sensor=false
Also in ios 5 Native Map application of iPhone show two popup saying Route1 and Route two and when user touch that selected route get highlighted .So can we also do same??
alternatives (optional), if set to
true, specifies that the Directions
service may provide more than one
route alternative in the response.
Note that providing route alternatives
may increase the response time from
the server.
From The Google Directions API
You need to add in your query link alternatives=true
see: Find the number of routes between two places
Here is Code
write this code
#pragma mark - MapView Delegate
//-----------------------------------------------------------------------
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
// [self.mapView removeAnnotation:self.annotation];
NSString *baseUrl = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%f,%f&destination=%f,%f&sensor=true", self.mapView.userLocation.location.coordinate.latitude, self.mapView.userLocation.location.coordinate.longitude, [[self.dictData valueForKey:#"latitude"]doubleValue],[[self.dictData valueForKey:#"longitude"]doubleValue]];
NSURL *url = [NSURL URLWithString:[baseUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSError *error = nil;
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
NSArray *routes = [result objectForKey:#"routes"];
NSDictionary *firstRoute = [routes objectAtIndex:0];
NSDictionary *leg = [[firstRoute objectForKey:#"legs"] objectAtIndex:0];
NSDictionary *end_location = [leg objectForKey:#"end_location"];
double latitude = [[end_location objectForKey:#"lat"] doubleValue];
double longitude = [[end_location objectForKey:#"lng"] doubleValue];
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude);
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = coordinate;
point.title = [leg objectForKey:#"end_address"];
point.subtitle = #"Event Destinations !!!";
[self.mapView addAnnotation:point];
NSArray *steps = [leg objectForKey:#"steps"];
int stepIndex = 0;
CLLocationCoordinate2D stepCoordinates[1 + [steps count] + 1];
stepCoordinates[stepIndex] = userLocation.coordinate;
for (NSDictionary *step in steps) {
NSDictionary *start_location = [step objectForKey:#"start_location"];
stepCoordinates[++stepIndex] = [self coordinateWithLocation:start_location];
if ([steps count] == stepIndex){
NSDictionary *end_location = [step objectForKey:#"end_location"];
stepCoordinates[++stepIndex] = [self coordinateWithLocation:end_location];
}
}
MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:stepCoordinates count:1 + stepIndex];
[self.mapView addOverlay:polyLine];
}];
}
#pragma mark - Custom Methods
//-----------------------------------------------------------------------
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay {
MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:overlay];
polylineView.strokeColor = [UIColor colorWithRed:204/255. green:45/255. blue:70/255. alpha:1.0];
polylineView.lineWidth = 10.0;
return polylineView;
}

How to get route length in mapKit

I'm using mapKit to draw a route from point to point. I did it.
But i want to get route length NOT the distance as straight line.
nextView.startPoint = [NSString stringWithFormat:#"%f,%f", userLatitude , userLongitude];
nextView.endPoint = [NSString stringWithFormat:#"%f,%f", 30.793636, 31.009641];
[diretions loadWithStartPoint:startPoint endPoint:endPoint options:options];
Aloso i want to give it a mid point to path through.
To do that you are going to have to use a directions API, preferably Google Directions API. You should look at that link and read it through, Apple does not have a built in direction API. You can send it a request and ask for JSON response, I would use AFNetworking to make like easier (on Github) and JSONKit also on Github for that. Then send a request and parse the JSON response. In the response you need the encoded points, which is a set of many coordinates that basically traces the route. You would then need to display that on an overlay. Here is some sample code, but before you copy and paste this in make sure you read the GDirections API Site, you will understand everything MUCH easier and can learn how to do more:
// DRAG IN AFNETWORKING FILES AND JSON KIT FILES TO YOUR PROJECT AND ALSO IMPORT THE MAP KIT AND CORE LOCATION FRAMEWORKS
// IMPORT FILES
#import "StringHelper.h"
#import "JSONKit.h"
#import "AFJSONRequestOperation.h"
#import "AFHTTPClient.h"
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
// DECLARE MUTABLE ARRAY IN .H:
NSMutableArray *_path;
// ADD THIS CODE TO WHEN YOU WANT TO REQUEST FOR DIRECTIONS
AFHTTPClient *_httpClient = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:#"http://maps.googleapis.com/"]];
[_httpClient registerHTTPOperationClass: [AFJSONRequestOperation class]];
[_httpClient setDefaultHeader:#"Accept" value:#"application/json"];
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
[parameters setObject:[NSString stringWithFormat:#"%f,%f", location.coordinate.latitude, location.coordinate.longitude] forKey:#"origin"];
[parameters setObject:[NSString stringWithFormat:#"%f,%f", location2.coordinate.latitude, location2.coordinate.longitude] forKey:#"destination"];
[parameters setObject:#"false" forKey:#"sensor"];
[parameters setObject:#"driving" forKey:#"mode"];
[parameters setObject:#"metric" forKey: #"units"];
NSMutableURLRequest *request = [_httpClient requestWithMethod:#"GET" path: #"maps/api/directions/json" parameters:parameters];
request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
AFHTTPRequestOperation *operation = [_httpClient HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSInteger statusCode = operation.response.statusCode;
if (statusCode == 200) {
[self parseResponse:responseObject];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { }];
[_httpClient enqueueHTTPRequestOperation:operation];
// NOW ADD THE PARSERESPONSE METHOD
- (void)parseResponse:(NSDictionary *)response {
NSString *status = [response objectForKey: #"status"];
NSArray *routes = [response objectForKey:#"routes"];
NSDictionary *routePath = [routes lastObject];
if (routePath) {
NSString *overviewPolyline = [[routePath objectForKey: #"overview_polyline"] objectForKey:#"points"];
_path = [self decodePolyLine:overviewPolyline];
NSInteger numberOfSteps = _path.count;
CLLocationCoordinate2D coordinates[numberOfSteps];
for (NSInteger index = 0; index < numberOfSteps; index++) {
CLLocation *location = [_path objectAtIndex:index];
CLLocationCoordinate2D coordinate = location.coordinate;
coordinates[index] = coordinate;
}
polyLine = [MKPolyline polylineWithCoordinates:coordinates count:numberOfSteps];
[self.mapView addOverlay:polyLine];
}
}
// IMPLEMENTING THE DECODEPOLYLINE METHOD:
-(NSMutableArray *)decodePolyLine:(NSString *)encodedStr {
NSMutableString *encoded = [[NSMutableString alloc] initWithCapacity:[encodedStr length]];
[encoded appendString:encodedStr];
[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 *location = [[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]];
[array addObject:location];
}
return array;
}
// IMPLEMENTING THE VIEWFOROVERLAY DELEGATE METHOD (MAKE SURE TO SET YOUR MAP VIEW'S DELEGATE TO SELF OR THIS WONT GET CALLED)
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay {
MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:overlay];
polylineView.strokeColor = [UIColor blueColor];
polylineView.lineWidth = 5.0;
polylineView.alpha = 0.7;
return polylineView;
}
And that should get your directional routes up and running!

Resources