I am trying to add multiple waypoints to my google directions request.
When I add a single waypoint like
https://maps.googleapis.com/maps/api/directions/json?&origin=51.507679,-0.125004&waypoints=51.524151,-0.123174&destination=51.495777,-0.108642&mode=walking
it works fine but when I try to add multiple waypoints like
https://maps.googleapis.com/maps/api/directions/json?&origin=51.606502,0.527309&waypoints=51.507679,-0.125004|51.524151,-0.123174&destination=51.495777,-0.108642&mode=walking
i receive a 'unsupported URL' error. What is the correct way to add multiple waypoints? Thanks
Its very simple, Just replace '|' with '%%7C'
Your updated url will be :
https://maps.googleapis.com/maps/api/directions/json?&origin=51.606502,0.527309&waypoints=51.507679,-0.125004%%7C51.524151,-0.123174&destination=51.495777,-0.108642&mode=walking
Happy Coding
I give you the solution step by step
First we should get the Google Map SDK
Drag the following bundles into your project (when prompted, select Copy items if needed):
Subspecs/Base/Frameworks/GoogleMapsBase.framework
Subspecs/Maps/Frameworks/GoogleMaps.framework
Subspecs/Maps/Frameworks/GoogleMapsCore.framework
Right-click GoogleMaps.framework in your project, and select Show In Finder.
Drag the GoogleMaps.bundle from the Resources folder into your project. When prompted, ensure Copy items into destination group's folder is not selected.
Select your project from the Project Navigator, and choose your application's target.
Open the Build Phases tab, and within Link Binary with Libraries, add the following frameworks:
GoogleMapsBase.framework
GoogleMaps.framework
GoogleMapsCore.framework
GoogleMapsM4B.framework (Premium Plan customers only)
Accelerate.framework
CoreData.framework
CoreGraphics.framework
CoreLocation.framework
CoreText.framework
GLKit.framework
ImageIO.framework
libc++.tbd
libz.tbd
OpenGLES.framework
QuartzCore.framework
SystemConfiguration.framework
UIKit.framework
Now Get the API key
Now you need to add following things in Plist
AppDelegate.m
#import GoogleMaps;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[GMSServices provideAPIKey:#"YOUR API KEY"];
return YES;
}
ViewController.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <GoogleMaps/GoogleMaps.h>
#interface ViewController : UIViewController<CLLocationManagerDelegate,GMSMapViewDelegate>{
CLLocation *currentLocation;
}
#property (strong, nonatomic) IBOutlet UIView *viewMarker;
#property (nonatomic, strong) CLLocationManager *locationManager;
#property (nonatomic, strong) GMSMapView *mapView;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize viewMarker,locationManager,
#synthesize mapView;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
locationManager = [[CLLocationManager alloc]init];
locationManager.delegate = self;
locationManager.distanceFilter = 10;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
if([CLLocationManager locationServicesEnabled] == NO){
NSLog(#"Your location service is not enabled, So go to Settings > Location Services");
}
else{
NSLog(#"Your location service is enabled");
}
if ([locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[locationManager requestWhenInUseAuthorization];
}
[locationManager startUpdatingLocation];
}
#pragma mark - CLLocationManagerDelegate method
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
currentLocation = [locations lastObject];
if (currentLocation != nil){
NSLog(#"The latitude value is - %#",[NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude]);
NSLog(#"The logitude value is - %#",[NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude]);
}
//Current
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:currentLocation.coordinate.latitude longitude: currentLocation.coordinate.longitude zoom:13];
self.mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
self.mapView.myLocationEnabled = YES;
self.mapView.delegate = self;
self.mapView.frame = viewMarker.bounds;
[viewMarker addSubview:self.mapView];
GMSMarker *marker1 = [[GMSMarker alloc] init];
//Current
marker1.position = CLLocationCoordinate2DMake(currentLocation.coordinate.latitude, currentLocation.coordinate.longitude);
marker1.icon = [UIImage imageNamed:#"boss-icon.png"];
marker1.map = self.spyMapView;
NSArray *arrLatLongValue = #[
#{
#"Latitude":#"12.9003",
#"Longitude":#"80.2278"
},
#{
#"Latitude":#"12.8447",
#"Longitude":#"80.2254"
},
#{
#"Latitude":#"12.7726",
#"Longitude":#"80.2488"
},
#{
#"Latitude":#"12.9171",
#"Longitude":#"80.1923"
}
];
NSString *strWayPoints = [NSString stringWithFormat:#"via:%f,%f", [arrLatLongValue[0][#"Latitude"] doubleValue], [arrLatLongValue[0][#"Longitude"] doubleValue]];
for(int j=0;j<arrLatLongValue.count;j++){
CLLocationCoordinate2D position = { [[arrLatLongValue[j] objectForKey:#"Latitude"] doubleValue], [[arrLatLongValue[j] objectForKey:#"Longitude"] doubleValue] };
GMSMarker *marker = [GMSMarker markerWithPosition:position];
marker.title = [NSString stringWithFormat:#"Marker %i", j];
marker.appearAnimation = YES;
marker.flat = YES;
if(j < 2)
marker.icon = [GMSMarker markerImageWithColor:[UIColor redColor]];
else if(j >= 2 && j < 4)
marker.icon = [GMSMarker markerImageWithColor:[UIColor purpleColor]];
else
marker.icon = [GMSMarker markerImageWithColor:[UIColor greenColor]];
if(j > 0)
strWayPoints = [NSString stringWithFormat:#"%#|via:%f,%f", strWayPoints, [arrLatLongValue[j][#"Latitude"] doubleValue], [arrLatLongValue[j][#"Longitude"] doubleValue]];
marker.map = self.mapView;
}
//Current
NSString *originString = [NSString stringWithFormat:#"%f,%f",currentLocation.coordinate.latitude, currentLocation.coordinate.longitude];
NSString *destinationString = [NSString stringWithFormat:#"%f,%f", #(12.9220085).doubleValue, #(80.0954032).doubleValue];
NSString *str = [NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/directions/json?origin=%#&destination=%#&waypoints=%#&key=YOUR API KEY",originString,destinationString,strWayPoints];
NSURL *url=[[NSURL alloc]initWithString:[str stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]]];
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSURLSessionDataTask * dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if(data == nil) {
return;
}else{
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSArray* latestRoutes = [json objectForKey:#"routes"];
NSString *points=[[[latestRoutes objectAtIndex:0] objectForKey:#"overview_polyline"] objectForKey:#"points"];
#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.
GMSPolyline *rectangle = [GMSPolyline polylineWithPath:path];
rectangle.strokeWidth=5.0;
rectangle.map = self.spyMapView;
[locationManager stopUpdatingLocation];
}
#catch (NSException * e) {
// TODO: show erro
}
}
}];
[dataTask resume];
}
[locationManager stopUpdatingLocation];
}
pragma mark - Drawing Lines
-(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;
}
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 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;
Hi I'm doing an app that must to show a map with the route. I parsed a Json to obtain the points to draw the polyline. I found a a code in the web to draw this polyline. The code I found it's on this link: http://iosguy.com/2012/05/22/tracing-routes-with-mapkit/
Where it says "Create the MKPolyline annotation" I tried to import this in my app, but I'm having problems to create the array of the coordinates. My method is this:
- (void)createMKpolylineAnnotation {
NSInteger numberOfSteps = self.path.count;
CLLocationCoordinate2D *coords = malloc(sizeof(CLLocationCoordinate2D) * numberOfSteps);
for (NSInteger index = 0; index < numberOfSteps; index++) {
CLLocation *location = [self.path objectAtIndex:index];
CLLocationCoordinate2D coordinate = location.coordinate;
coords[index] = coordinate;
}
MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:coords count:numberOfSteps];
[self.mapView addOverlay:polyLine];
}
When I try to look the value of coords is setted only the first time, why's that?
Can you help me to solve this problem or i should make in another mode?
I post here the code of the view controller that handle the map view.
MapViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MapViewController : UIViewController <MKMapViewDelegate>
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
#property (nonatomic, strong) NSString *fromCity;
#property (nonatomic, strong) NSString *toCity;
- (IBAction)chooseKindOfMap:(id)sender;
#end
MapViewController.m
#import "MapViewController.h"
#import "AppDelegate.h"
#import "PlaceAnnotation.h"
#interface MapViewController ()
#property (nonatomic, strong)NSMutableArray *mapAnnotation;
#property (nonatomic) BOOL needUpdateRegion;
#property (nonatomic, strong)NSMutableArray *path;
#end
#implementation MapViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self parseGoogleJsonToObtainPointsForPolyline];
[self.mapView setDelegate:self];
self.needUpdateRegion = YES;
//[self centerMap];
self.mapAnnotation = [[NSMutableArray alloc]initWithCapacity:2];
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
NSLog(#"%d", appDelegate.dataForMap.count);
NSArray* coords = [self getCoords:appDelegate.dataForMap];
NSLog(#"coords = %#", coords);
PlaceAnnotation *fromPlace = [[PlaceAnnotation alloc] initWithCoordinateAndName:coords[0] andLong:coords[1] andName:self.fromCity];
PlaceAnnotation *toPlace = [[PlaceAnnotation alloc] initWithCoordinateAndName:coords[2] andLong:coords[3] andName:self.toCity];
[self.mapAnnotation insertObject:fromPlace atIndex:0];
[self.mapAnnotation insertObject:toPlace atIndex:1];
NSLog(#"mapAnnotation.count: %d", self.mapAnnotation.count);
if (self.mapAnnotation) {
[self.mapView removeAnnotations:self.mapView.annotations];
}
[self.mapView addAnnotation:self.mapAnnotation[0]];
[self.mapView addAnnotation:self.mapAnnotation[1]];
NSLog(#"MapAnnotation = %#", self.mapView.annotations);
[self updateRegion];
[self createMKpolylineAnnotation];
}
//- (void)viewDidAppear:(BOOL)animated {
// [super viewDidAppear:animated];
// if (self.needUpdateRegion) [self updateRegion];
//}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (MKAnnotationView*)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
MKPinAnnotationView *pin = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:nil];
pin.pinColor = MKPinAnnotationColorRed;
return pin;
}
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
MKPinAnnotationView *ulv = [mapView viewForAnnotation:mapView.userLocation];
ulv.hidden = YES;
}
- (NSArray*)getCoords:(NSDictionary*)data {
NSArray *legs = [data objectForKey:#"legs"];
NSDictionary *firstZero = [legs objectAtIndex:0];
NSDictionary *endLocation = [firstZero objectForKey:#"end_location"];
NSDictionary *startLocation = [firstZero objectForKey:#"start_location"];
NSString *latFrom = [startLocation objectForKey:#"lat"];
NSString *lngFrom = [startLocation objectForKey:#"lng"];
NSString *latTo = [endLocation objectForKey:#"lat"];
NSString *lngTo = [endLocation objectForKey:#"lng"];
return #[latFrom,lngFrom,latTo,lngTo];
}
- (void)centerMap {
MKCoordinateRegion region;
region.center.latitude = 41.178654;
region.center.longitude = 11.843262;
region.span.latitudeDelta = 11.070406;
region.span.longitudeDelta = 12.744629;
[self.mapView setRegion:region];
}
- (IBAction)chooseKindOfMap:(id)sender {
if ([sender tag] == 0) {
self.mapView.mapType = MKMapTypeStandard;
}
if ([sender tag] == 1) {
self.mapView.mapType = MKMapTypeSatellite;
}
if ([sender tag] == 2) {
self.mapView.mapType = MKMapTypeHybrid;
}
}
- (void)updateRegion
{
self.needUpdateRegion = NO;
CGRect boundingRect;
BOOL started = NO;
for (id <MKAnnotation> annotation in self.mapView.annotations) {
CGRect annotationRect = CGRectMake(annotation.coordinate.latitude, annotation.coordinate.longitude, 0, 0);
if (!started) {
started = YES;
boundingRect = annotationRect;
} else {
boundingRect = CGRectUnion(boundingRect, annotationRect);
}
}
if (started) {
boundingRect = CGRectInset(boundingRect, -0.2, -0.2);
if ((boundingRect.size.width < 20) && (boundingRect.size.height < 20)) {
MKCoordinateRegion region;
region.center.latitude = boundingRect.origin.x + boundingRect.size.width / 2;
region.center.longitude = boundingRect.origin.y + boundingRect.size.height / 2;
region.span.latitudeDelta = boundingRect.size.width;
region.span.longitudeDelta = boundingRect.size.height;
[self.mapView setRegion:region animated:YES];
}
}
}
- (void)parseGoogleJsonToObtainPointsForPolyline {
NSDictionary *polyline;
NSMutableArray *points = [[NSMutableArray alloc]init];;
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
NSArray *legs = [appDelegate.dataForMap objectForKey:#"legs"];
NSDictionary *firstZero =[legs objectAtIndex:0];
NSArray *steps = [firstZero objectForKey:#"steps"];
for (int i = 0; i < steps.count; i++) {
polyline = [steps[i] objectForKey:#"polyline"];
[points addObject:polyline[#"points"]];
NSLog(#"POINTS = %#", polyline[#"points"]);
self.path = [self decodePolyLine:points[i]];
}
NSLog(#"path = %#", self.path);
}
-(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;
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay {
MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:overlay];
polylineView.strokeColor = [UIColor redColor];
polylineView.lineWidth = 1.0;
return polylineView;
}
- (void)createMKpolylineAnnotation {
NSInteger numberOfSteps = self.path.count;
CLLocationCoordinate2D *coords = malloc(sizeof(CLLocationCoordinate2D) * numberOfSteps);
for (NSInteger index = 0; index < numberOfSteps; index++) {
CLLocation *location = [self.path objectAtIndex:index];
CLLocationCoordinate2D coordinate = location.coordinate;
coords[index] = coordinate;
}
MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:coords count:numberOfSteps];
[self.mapView addOverlay:polyLine];
}
#end
I used the AppDelegate to have the Json (I parsed it in another class)
Here is a tutorial how to add a polyline to a mapView. Hope this helps!
EDIT:
Unfortunately, the link provided above is now broken, and I am not able to find the tutorial referred to.
simple, just copy and paste my code and modify some variables
- (IBAction)traceRoute:(UIButton *)sender {
double latDouble = 39.7540615;
double lngDouble = -8.8059587;
// double latDouble = [self.sheetDetail.data.locationLat doubleValue];
// double lngDouble = [self.sheetDetail.data.locationLng doubleValue];
CLLocationCoordinate2D c2D = CLLocationCoordinate2DMake(latDouble, lngDouble);
MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:c2D addressDictionary:nil];
MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
[mapItem setName:#"Mobile Edge"];
MKPlacemark *placemark2;
MKMapItem *mapItem2;
if(kIS_OS_8_OR_LATER) {
placemark2 = [[MKPlacemark alloc] initWithCoordinate:_userLoc addressDictionary:nil];
mapItem2 = [[MKMapItem alloc] initWithPlacemark:placemark2];
[mapItem2 setName:#"Me"];
} else {
placemark2 = [[MKPlacemark alloc] initWithCoordinate:_mapView.userLocation.coordinate addressDictionary:nil];
mapItem2 = [[MKMapItem alloc] initWithPlacemark:placemark2];
[mapItem2 setName:#"Me"];
}
MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
request.source = mapItem2;
request.destination = mapItem;
request.requestsAlternateRoutes = NO;
MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
[directions calculateDirectionsWithCompletionHandler:
^(MKDirectionsResponse *response, NSError *error) {
if (error) {
// Handle error
[[NSNotificationCenter defaultCenter] postNotificationName:#"finishedLocationRoute" object:nil];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: NSLocalizedString(#"Route error title", nil)
message: NSLocalizedString(#"Route error", nil)
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
} else {
for (MKRoute *route in response.routes)
{
//MKMapPoint middlePoint = route.polyline.points[route.polyline.pointCount/2];
//[self createAndAddAnnotationForCoordinate:MKCoordinateForMapPoint(middlePoint) andRoute:route];
[self.mapView addOverlay:route.polyline level:MKOverlayLevelAboveRoads];
}
//notifies parent menu
//[[NSNotificationCenter defaultCenter] postNotificationName:#"finishedLocationRoute" object:nil];
}
}];
}
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id)overlay
{
if (![overlay isKindOfClass:[MKPolygon class]]) {
MKPolyline *route = overlay;
MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithPolyline:route];
renderer.strokeColor = [UIColor blueColor];
renderer.lineWidth = 5.0;
return renderer;
} else {
return nil;
}
}
So I'm attempting to integrate the user's current location with my iOS project - I'm using some third part code to build out the map with the pinpoints - I have these frameworks integrated:
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <QuartzCore/QuartzCore.h>
#import <MapKit/MapKit.h>
here's my code with the pinpoints - any help would be greatly appreciated:
#import "asyMap.h"
#implementation asyMap
#synthesize currentAnnotation,mapAnnotations,map,prompt,mapFromLink,selectedAnnotationId,selectedAnnotationIndex,showOthers,useCustomTitle,customTitle;
/**
* Class constructor
*/
-(id)init{
self = [super init];
if(self){
useCustomTitle = FALSE;
mapFromLink = FALSE;
showOthers = FALSE;
map = [[asyMapObject alloc] init];
[map addOnView:self.view];
}
return self;
}
/**
* Overwrite the set page method in
* order to show a selected annotation
* from a link
*/
-(void)setPage:(NSDictionary *)page{
NSDictionary *metas = [page valueForKey:#"metas"];
if([metas valueForKey:#"selectedAnnotationPageTitle"] && ![[[metas valueForKey:#"selectedAnnotationPageTitle"] stringValue] isEqualToString:#""] && customTitle == nil){
useCustomTitle = TRUE;
NSString *newTitle = [metas valueForKey:#"selectedAnnotationPageTitle"];
customTitle = [[NSString alloc] initWithString:[[newTitle stringByReplacingOccurrencesOfString:#"+" withString:#" "] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
if(useCustomTitle && customTitle != nil){
NSMutableDictionary *pageWithCustomTitle = [[NSMutableDictionary alloc] initWithDictionary:page];
[pageWithCustomTitle setValue:customTitle forKey:#"title"];
[super
setPage:pageWithCustomTitle];
}else{
[super setPage:page];
}
if([metas valueForKey:#"annotationFromLink"] && [[[metas valueForKey:#"annotationFromLink"] stringValue] isEqualToString:#"yes"] && selectedAnnotationId == nil){
selectedAnnotationId = [[NSString alloc] initWithString:[metas valueForKey:#"selectedAnnotation"]];
mapFromLink = TRUE;
showOthers = [[[metas valueForKey:#"showOthers"] stringValue] isEqualToString:#"yes"];
}else if(mapFromLink && selectedAnnotationId != nil){
mapFromLink = FALSE;
NSArray *annotations = [page valueForKey:#"annotations"];
for(int a = 0; a < [annotations count]; a++){
NSDictionary *annotation = [annotations objectAtIndex:a];
if([[[annotation valueForKey:#"annotationId"] stringValue] isEqualToString:selectedAnnotationId]){
mapFromLink = TRUE;
selectedAnnotationIndex = a;
break;
}
}
}
}
/**
* Set the module's name
*/
-(void)makeProcess{
[self setModuleName:#"map"];
}
/**
* Create the basic prompt alert
*/
-(void)buildModule{
prompt = [[UIAlertView alloc] initWithTitle:#"" message:[theme asy__:#"Open on the Maps app?"] delegate:self cancelButtonTitle:[theme asy__:#"No"] otherButtonTitles:[theme asy__:#"Yes"], nil];
}
/**
* Set the annotations after get the page data
*/
-(void)requestedPage:(NSDictionary *)pageInformation{
[self setPage:pageInformation];
if(mapFromLink && !showOthers && [[self getPageMapAnnotations] count] > 0){
NSArray *pageAnnotations = [self getPageMapAnnotations];
mapAnnotations = [[NSArray alloc] initWithObjects:[pageAnnotations objectAtIndex:selectedAnnotationIndex],nil];
}else{
mapAnnotations = [[NSArray alloc] initWithArray:[self getPageMapAnnotations]];
}
[map setMapAnnotations:mapAnnotations andDelegate:self];
if(mapFromLink){
[map focusMapOnAnnotationAtIndex:(showOthers ? selectedAnnotationIndex : 0)];
}
[map build];
[self hideLoading];
[self checkPageOptionButton];
}
/**
* The module orientation did change
*/
-(void)moduleOrientationDidChange{
[map setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
}
#pragma mark - Map Delegate
/**
* Check if the annotation has properties for action or the prompt to be opened
* on the Maps app should appear
*/
-(void)asyMapObject:(asyMapObject *)mapObject didSelectAnnotation:(NSDictionary *)annotation atIndex:(NSInteger)index{
currentAnnotation = index;
if([[annotation valueForKey:#"menuId"] isEqualToString:#"0"] &&
[[annotation valueForKey:#"pageId"] isEqualToString:#"0"] &&
[[annotation valueForKey:#"link"] isEqualToString:#""] &&
[[annotation valueForKey:#"url"] isEqualToString:#""] &&
[[annotation valueForKey:#"phpfile"] isEqualToString:#""]){
[prompt setTitle:[annotation valueForKey:#"title"]];
[prompt show];
}else{
AppsifymeCore *core = [AppsifymeCore sharedAppsifymeCore];
[core basicHandlerForMultiActionsOption:annotation];
}
}
#pragma mark - Alert view delegate
/**
* Detect if the user wants to open the annotation on the maps app, and if its
* true, this method build the link and open the app
*/
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if(buttonIndex != 1) return;
AppsifymeCore *core = [AppsifymeCore sharedAppsifymeCore];
NSDictionary *annotation = [mapAnnotations objectAtIndex:currentAnnotation];
float latitude = [[annotation valueForKey:#"latitude"] floatValue];
float longitude = [[annotation valueForKey:#"longitude"] floatValue];
if(![core asyiOS6]){
NSString *pinName = [[NSString alloc] initWithString:[core encodeURLParameter:[annotation valueForKey:#"title"]]];
int zoom = 13;
NSString *stringURL = [[NSString alloc] initWithFormat:#"http://maps.apple.com/maps?q=%##%1.6f,%1.6f&z=%d", pinName, latitude, longitude, zoom];
NSURL *url = [[NSURL alloc] initWithString:stringURL];
[[UIApplication sharedApplication] openURL:url];
}else{
Class itemClass = [MKMapItem class];
if (itemClass && [itemClass respondsToSelector:#selector(openMapsWithItems:launchOptions:)]) {
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude,longitude);
MKPlacemark *placeMark = [[MKPlacemark alloc] initWithCoordinate:coordinate addressDictionary:nil];
MKMapItem *item = [[MKMapItem alloc] initWithPlacemark:placeMark];
item.name = [[annotation valueForKey:#"title"] stringValue];
[item openInMapsWithLaunchOptions:nil];
}
}
}
#end
In your init method, add this line
self.showsUserLocation = YES;
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!