iPhone: How to draw line between two points on MapKit? - iphone

I have Latitude and Longitude of two points and Want to Draw line between these two points with Pin on MapKit.
I have googled but Could not find some suitable solution because the one I found was drawing overlay with array of Data points but I do not have any array of points between these two points.
Just two points and want to draw line between these two points.
Please help.

First make your view controller implement the MKMapViewDelegate protocol and declare the properties you will need:
#property (nonatomic, retain) MKMapView *mapView; //this is your map view
#property (nonatomic, retain) MKPolyline *routeLine; //your line
#property (nonatomic, retain) MKPolylineView *routeLineView; //overlay view
then in viewDidLoad (for example, or wherever you initialize)
//initialize your map view and add it to your view hierarchy - **set its delegate to self***
CLLocationCoordinate2D coordinateArray[2];
coordinateArray[0] = CLLocationCoordinate2DMake(lat1, lon1);
coordinateArray[1] = CLLocationCoordinate2DMake(lat2, lon2);
self.routeLine = [MKPolyline polylineWithCoordinates:coordinateArray count:2];
[self.mapView setVisibleMapRect:[self.routeLine boundingMapRect]]; //If you want the route to be visible
[self.mapView addOverlay:self.routeLine];
then implement the MKMapViewDelegate's method -(MKOverlayView *)mapView:viewForOverlay:
-(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{
if(overlay == self.routeLine)
{
if(nil == self.routeLineView)
{
self.routeLineView = [[[MKPolylineView alloc] initWithPolyline:self.routeLine] autorelease];
self.routeLineView.fillColor = [UIColor redColor];
self.routeLineView.strokeColor = [UIColor redColor];
self.routeLineView.lineWidth = 5;
}
return self.routeLineView;
}
return nil;
}
You can adjust the code to fit your need, but it's pretty much straight forward for 2 or more points.

Please See this tutorial to draw polyline or route in mkmapview
1>Draw route using mapkit
2>From versions above ios4.0 You can use MKOverlayPathView See Apple Docs
Sample code :-
create PolyLine:-
-(void) loadRoute
{
NSString* filePath = [[NSBundle mainBundle] pathForResource:#”route” ofType:#”csv”];
NSString* fileContents = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
NSArray* pointStrings = [fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
MKMapPoint northEastPoint;
MKMapPoint southWestPoint;
MKMapPoint* pointArr = malloc(sizeof(CLLocationCoordinate2D) * pointStrings.count);
for(int idx = 0; idx < pointStrings.count; idx++)
{
NSString* currentPointString = [pointStrings objectAtIndex:idx];
NSArray* latLonArr = [currentPointString componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#","]];
CLLocationDegrees latitude = [[latLonArr objectAtIndex:0] doubleValue];
CLLocationDegrees longitude = [[latLonArr objectAtIndex:1] doubleValue];
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude);
MKMapPoint point = MKMapPointForCoordinate(coordinate);
if (idx == 0) {
northEastPoint = point;
southWestPoint = point;
}
else
{
if (point.x > northEastPoint.x)
northEastPoint.x = point.x;
if(point.y > northEastPoint.y)
northEastPoint.y = point.y;
if (point.x < southWestPoint.x)
southWestPoint.x = point.x;
if (point.y < southWestPoint.y)
southWestPoint.y = point.y;
}
pointArr[idx] = point;
}
self.routeLine = [MKPolyline polylineWithPoints:pointArr count:pointStrings.count];
_routeRect = MKMapRectMake(southWestPoint.x, southWestPoint.y, northEastPoint.x - southWestPoint.x, northEastPoint.y - southWestPoint.y);
free(pointArr);
}
Display PoluLine :-
[self.mapView addOverlay:self.routeLine];
Adding the overlay alone will not render anything on the map. Your MKMapViewDelegate implementation must return an overlay for this route you’ve just added as simply adding won't help .
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id )overlay
{
MKOverlayView* overlayView = nil;
if(overlay == self.routeLine)
{
//if we have not yet created an overlay view for this overlay, create it now.
if(nil == self.routeLineView)
{
self.routeLineView = [[[MKPolylineView alloc] initWithPolyline:self.routeLine] autorelease];
self.routeLineView.fillColor = [UIColor redColor];
self.routeLineView.strokeColor = [UIColor redColor];
self.routeLineView.lineWidth = 3;
}
overlayView = self.routeLineView;
}
return overlayView;
}

#import <MapKit/MapKit.h>
- (void)viewDidLoad
{
[mapview setDelegate:self];
mapview.showsUserLocation = YES;
}
- (CLLocationCoordinate2D)coordinateWithLocation:(NSDictionary*)location
{
double latitude = [[location objectForKey:#"lat"] doubleValue];
double longitude = [[location objectForKey:#"lng"] doubleValue];
return CLLocationCoordinate2DMake(latitude, longitude);
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
MKCoordinateSpan span = MKCoordinateSpanMake(0.005, 0.005);
MKCoordinateRegion region = MKCoordinateRegionMake(userLocation.location.coordinate, span);
[mapview setRegion:region];
[mapview setCenterCoordinate:userLocation.coordinate animated:YES];
NSString *baseUrl = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%f,%f&destination=%#&sensor=true", mapview.userLocation.location.coordinate.latitude, mapview.userLocation.location.coordinate.longitude, #"24.1620661,72.394131"];
//http://maps.googleapis.com/maps/api/directions/json?origin=23.030000,72.580000&destination=23.400000,72.750000&sensor=true
NSURL *url = [NSURL URLWithString:[baseUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSLog(#"%#",url);
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"];
NSLog(#"%#",routes);
NSDictionary *firstRoute = [routes objectAtIndex:0];
NSDictionary *leg = [[firstRoute objectForKey:#"legs"] objectAtIndex:0];
NSDictionary *end_location = [leg objectForKey:#"end_location"];
NSLog(#"dDDDDDD>>>>>>%#",leg);
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 = #"I'm here!!!";
[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];
[mapview addOverlay:polyLine];
CLLocationCoordinate2D centerCoordinate = CLLocationCoordinate2DMake((userLocation.location.coordinate.latitude + coordinate.latitude)/2, (userLocation.location.coordinate.longitude + coordinate.longitude)/2);
}];
}
then implement the MKMapViewDelegate's method -(MKOverlayView *)mapView:viewForOverlay:
- (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 = 1;
return polylineView;
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString *annotaionIdentifier=#"annotationIdentifier";
MKPinAnnotationView *aView=(MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:annotaionIdentifier ];
if (aView==nil) {
aView=[[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:annotaionIdentifier];
aView.pinColor = MKPinAnnotationColorRed;
aView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
// aView.image=[UIImage imageNamed:#"arrow"];
aView.animatesDrop=TRUE;
aView.canShowCallout = YES;
aView.calloutOffset = CGPointMake(-5, 5);
}
return aView;
}

First of all Add frame work
1 Foundation.framework
2 CoreGraphics.framework
3 CoreLocation.framework
4 MapKit.framework
Then create nsobject file Like see.... TrailsMap.h File
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface TrailsMap : NSObject<MKAnnotation>
{
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *image;
NSString *subtitle;
}
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (nonatomic,copy) NSString *title;
#property (nonatomic,copy) NSString *image;
#property (nonatomic,copy) NSString *subtitle;
- (id)initWithLocation:(CLLocationCoordinate2D)coord;
TrailsMap.m
#import "TrailsMap.h"
#implementation TrailsMap
#synthesize coordinate,title,image,subtitle;
- (id)initWithLocation:(CLLocationCoordinate2D)coord{
self = [super init];
if (self) {
coordinate = coord;
}
return self;
}
Now Create coding in mainview Please see..
ViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface ViewController : UIViewController<MKMapViewDelegate>
#property (strong, nonatomic) IBOutlet MKMapView *MapView;
#property (nonatomic, retain) MKPolyline *routeLine;
#property (nonatomic, retain) MKPolylineView *routeLineView;
-(void)LoadMapRoute;
#end
Finally create coding in mainview.m file
ViewController.m
#import "ViewController.h"
#import "TrailsMap.h"
#interface ViewController ()
{
NSData *alldata;
NSMutableDictionary *data1;
NSMutableArray *RouteLocation;
NSMutableArray *RouteName;
}
#end
#implementation ViewController
#synthesize MapView,routeLine,routeLineView;
- (void)viewDidLoad
{
[super viewDidLoad];
RouteName = [[NSMutableArray alloc] initWithObjects:#"Ahmedabad",#"Rajkot", nil];
RouteLocation = [[NSMutableArray alloc] initWithObjects:#"23.0300,72.5800",#"22.3000,70.7833", nil];
[self LoadMapRoute];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
//-------------------------------------
// ************* Map ******************
//-------------------------------------
-(void)LoadMapRoute
{
MKCoordinateSpan span = MKCoordinateSpanMake(0.8, 0.8);
MKCoordinateRegion region;
region.span = span;
region.center= CLLocationCoordinate2DMake(23.0300,72.5800);
// Distance between two address
NSArray *coor1=[[RouteLocation objectAtIndex:0] componentsSeparatedByString:#","];
CLLocation *locA = [[CLLocation alloc] initWithLatitude:[[coor1 objectAtIndex:0] doubleValue] longitude:[[coor1 objectAtIndex:1] doubleValue]];
NSArray *coor2=[[RouteLocation objectAtIndex:1] componentsSeparatedByString:#","];
CLLocation *locB = [[CLLocation alloc] initWithLatitude:[[coor2 objectAtIndex:0] doubleValue] longitude:[[coor2 objectAtIndex:1] doubleValue]];
CLLocationDistance distance = [locA distanceFromLocation:locB];
NSLog(#"Distance :%.0f Meters",distance);
NSString *baseUrl = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%#&destination=%#&sensor=true", [RouteLocation objectAtIndex:0],[RouteLocation objectAtIndex:1] ];
NSURL *url = [NSURL URLWithString:[baseUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
alldata = [[NSData alloc] initWithContentsOfURL:url];
NSError *err;
data1 =[NSJSONSerialization JSONObjectWithData:alldata options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves error:&err];
if (err)
{
NSLog(#" %#",[err localizedDescription]);
}
NSArray *routes = [data1 objectForKey:#"routes"];
NSDictionary *firstRoute = [routes objectAtIndex:0];
NSDictionary *leg = [[firstRoute objectForKey:#"legs"] objectAtIndex:0];
NSArray *steps = [leg objectForKey:#"steps"];
int stepIndex = 0;
CLLocationCoordinate2D stepCoordinates[[steps count]+1 ];
for (NSDictionary *step in steps)
{
NSDictionary *start_location = [step objectForKey:#"start_location"];
double latitude = [[start_location objectForKey:#"lat"] doubleValue];
double longitude = [[start_location objectForKey:#"lng"] doubleValue];
stepCoordinates[stepIndex] = CLLocationCoordinate2DMake(latitude, longitude);
if (stepIndex==0)
{
TrailsMap *point=[[TrailsMap alloc] initWithLocation:stepCoordinates[stepIndex]];
point.title =[RouteName objectAtIndex:0];
point.subtitle=[NSString stringWithFormat:#"Distance :%.0f Meters",distance];
[self.MapView addAnnotation:point];
}
if (stepIndex==[steps count]-1)
{
stepIndex++;
NSDictionary *end_location = [step objectForKey:#"end_location"];
double latitude = [[end_location objectForKey:#"lat"] doubleValue];
double longitude = [[end_location objectForKey:#"lng"] doubleValue];
stepCoordinates[stepIndex] = CLLocationCoordinate2DMake(latitude, longitude);
TrailsMap *point=[[TrailsMap alloc] initWithLocation:stepCoordinates[stepIndex]];
point.title = [RouteName objectAtIndex:1];
point.subtitle=[NSString stringWithFormat:#"Distance :%.0f Meters",distance];
[self.MapView addAnnotation:point];
}
stepIndex++;
}
MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:stepCoordinates count: stepIndex];
[MapView addOverlay:polyLine];
[MapView setRegion:region animated:YES];
}
- (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 = 5;
return polylineView;
}
If You want to set multiple pin in map then just add this code.
Annotaion is Objectfile.
-(void)LoadMultiplePin
{
RouteName = [[NSMutableArray alloc] initWithObjects:#"Ahmedabad",#"Rajkot",#"Limdi", nil];
RouteLocation = [[NSMutableArray alloc] initWithObjects:#"23.0300,72.5800",#"22.3000,70.7833",#"22.5728,71.8114", nil];
MKCoordinateSpan span = MKCoordinateSpanMake(2.9, 2.9);
MKCoordinateRegion region;
region.span = span;
region.center= CLLocationCoordinate2DMake(22.5728,71.8114);
int cnt=RouteLocation.count;
for (int p=0 ; p<cnt ; p++ )
{
NSArray *coor=[[RouteLocation objectAtIndex:p] componentsSeparatedByString:#","];
CLLocationCoordinate2D location=CLLocationCoordinate2DMake([[coor objectAtIndex:0] doubleValue],[[coor objectAtIndex:1] doubleValue]);
Annotaion *point=[[Annotaion alloc] initWithLocation:location];
point.title =[RouteName objectAtIndex:p];
[Map addAnnotation:point];
}
[Map setRegion:region animated:YES];
}
By using this code You can easily Drope two pin and draw line between that two Pin
Enjoy Happy Coding...:)

I took the great answer from #graver and did this for Swift 3:
// Called from viewDidLoad
func setupMap() {
mapView.delegate = self
// BusStop implements the MKAnnotation protocol, I have an array of them
let routeCoordinates = busStops.map({ $0.coordinate })
let routeLine = MKPolyline(coordinates: routeCoordinates, count: routeCoordinates.count)
mapView.setVisibleMapRect(routeLine.boundingMapRect, animated: false)
mapView.add(routeLine)
}
// MARK: MKMapViewDelegate
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let polyline = overlay as? MKPolyline {
let polylineRenderer = MKPolylineRenderer(overlay: polyline)
polylineRenderer.strokeColor = .blue
polylineRenderer.lineWidth = 3
return polylineRenderer
}
return MKOverlayRenderer(overlay: overlay)
}

I have created demo in swift with continue update location on map with polyline.
Please follow below steps :
1) Create new project and set up required things.
2) Go to project target->Build Phases -> Link Binary with Libraries and add
MapKit.framwork, CoreLocation.framework.
3) Go to sotryboard and add mapview and linkup with your viewcontroller.
4) Add properties and delegates that i am providing code below.
ViewController.Swift
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController,CLLocationManagerDelegate,MKMapViewDelegate{
#IBOutlet weak var mapView:MKMapView!
var locationManager: CLLocationManager!
var routeArr:[CLLocationCoordinate2D] = []
var isStarted:Bool = false
// MARK:- Life cycle
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.delegate = self;
locationManager.startMonitoringSignificantLocationChanges()
locationManager.allowsBackgroundLocationUpdates = true
locationManager.pausesLocationUpdatesAutomatically = false
// user activated automatic authorization info mode
let status = CLLocationManager.authorizationStatus()
if status == .notDetermined || status == .denied || status == .authorizedWhenInUse {
// present an alert indicating location authorization required
// and offer to take the user to Settings for the app via
// UIApplication -openUrl: and UIApplicationOpenSettingsURLString
locationManager.requestAlwaysAuthorization()
locationManager.requestWhenInUseAuthorization()
}
locationManager.startUpdatingLocation()
locationManager.startUpdatingHeading()
mapView.delegate = self
mapView.showsUserLocation = true
mapView.mapType = MKMapType(rawValue: 0)!
mapView.userTrackingMode = MKUserTrackingMode(rawValue: 2)!
}
// MARK:- Button Actions
#IBAction func startBtnClick(_ sender: Any) {
isStarted = true
}
#IBAction func endBtnClick(_ sender: Any) {
isStarted = false
routeArr.removeAll()
}
// MARK:- LocationManager Delegate
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last
if isStarted == true {
if locations.count > 0 {
let newLocation:CLLocationCoordinate2D = (location?.coordinate ?? nil)!
routeArr.append(newLocation)
DispatchQueue.main.async {
if self.routeArr.count > 2 {
let route:[CLLocationCoordinate2D] = [self.routeArr[self.routeArr.count - 2] ,self.routeArr.last!]
print(route)
let polyline = MKPolyline(coordinates: route, count: route.count)
self.mapView.addOverlay(polyline)
}
}
}
}
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if (overlay is MKPolyline) {
let pr = MKPolylineRenderer(overlay: overlay)
pr.strokeColor = UIColor.red
pr.fillColor = .green
pr.lineWidth = 5
return pr
}else {
return MKOverlayRenderer()
}
}
}
Run your project and click on start button for tracking and you can see polyline on map. If you click on stop button then it will stop to draw polyline.
Thankyou

pass your address cordination
-(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) f to: (CLLocationCoordinate2D) t {
NSString* saddr = [NSString stringWithFormat:#"%f,%f", f.latitude, f.longitude];
NSString* daddr = [NSString stringWithFormat:#"%f,%f", t.latitude, t.longitude];
NSString* apiUrlStr = [NSString stringWithFormat:#"http://maps.google.com/maps? output=dragdir&saddr=%#&daddr=%#", saddr, daddr];
// NSString* apiUrlStr = #"http://maps.google.com/maps?output=dragdir&saddr=40.769264,-73.958995&daddr=47.286522,-122.312932";
NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
NSLog(#"api url: %#", apiUrl);
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSUTF8StringEncoding error:nil];
NSString* encodedPoints = [apiResponse stringByMatching:#"points:\\\"([^\\\"]*)\\\"" capture:1L];
return [self decodePolyLine:[encodedPoints mutableCopy]];
}
-(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;
}
-(void) updateRouteView:(UIColor *)clr {
CGContextRef context =CGBitmapContextCreate(nil,routeView.frame.size.width,routeView.frame.size.height,8,4 * routeView.frame.size.width,CGColorSpaceCreateDeviceRGB(), kCGImageAlphaPremultipliedLast);
CGContextSetStrokeColorWithColor(context, clr.CGColor);
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextSetLineWidth(context, 3.0);
for(int i = 0; i < routes.count; i++) {
CLLocation* location = [routes objectAtIndex:i];
CGPoint point = [mapView convertCoordinate:location.coordinate toPointToView:routeView];
if(i == 0) {
CGContextMoveToPoint(context, point.x, routeView.frame.size.height - point.y);
} else {
CGContextAddLineToPoint(context, point.x, routeView.frame.size.height - point.y);
}
}
CGContextStrokePath(context);
CGImageRef image = CGBitmapContextCreateImage(context);
UIImage* img = [UIImage imageWithCGImage:image];
routeView.image = img;
CGContextRelease(context);
}

You can draw lines in map using MKPolyline.
See this link
http://spitzkoff.com/craig/?p=136
ALSO:
https://github.com/kishikawakatsumi/MapKit-Route-Directions
http://cloudmade.com/
These are all tutorials and open source libraries which you can easily refer to. Currently MapKit does not support this feature...

here you must calculate the route with its latitude and longtitude and then draw the poly line on MapView........
I do this things in my app....i draw route on mapview with all information....
here if you MapKit and also use RagexKitLite then its too simple for you just get Demo of RagexKitLite....

Get full code:https://github.com/javedmultani16/MapKitWithPolyLine
Draw line like:
directionsRequest.transportType = MKDirectionsTransportType.automobile
//Draw polyline by using MKRoute so it follows the street roads...
for (k, item) in arrayarrayPlacemarks.enumerated() {
if k < (arrayarrayPlacemarks.count - 1) {
directionsRequest.source = item
directionsRequest.destination = arrayarrayPlacemarks[k+1]
let directions = MKDirections(request: directionsRequest)
directions.calculate { (response:MKDirections.Response!, error: Error!) -> Void in
if error == nil {
self.locRoute = response.routes[0] as? MKRoute
let geodesic:MKPolyline = self.locRoute!.polyline
self.mapView.addOverlay(geodesic)
}
}
}
}
Delegate method :
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if overlay.isKind(of: MKPolyline.self){
var polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.fillColor = UIColor.blue
polylineRenderer.strokeColor = UIColor.blue
polylineRenderer.lineWidth = 2
return polylineRenderer
}
return MKOverlayRenderer(overlay: overlay)
}

Related

Setting region in MKMapView

I have 10 - 15 lat long to show in map at a time. How should I set region so that I can see all the annotations on the map.
create class as below. create two class: ViewController is class of UIViewController and MapViewAnnotation is class of NSObject. I have created that two class as below. bind mapview in XIB of ViewController and set delegate.
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "MapViewAnnotation.h"
#interface ViewController : UIViewController<MKMapViewDelegate>{
IBOutlet MKMapView* mapView;
NSMutableArray *arrayLocation;
}
#end
#import "ViewController.h"
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
arrayLocation = [[NSMutableArray alloc]init];
NSMutableArray *arrAnnotations = [[NSMutableArray alloc]init];
NSMutableDictionary *dict = [[NSMutableDictionary alloc]init];
[dict setValue:#"32.774125" forKey:#"latitude"];
[dict setValue:#"-117.240658" forKey:#"longitude"];
[dict setValue:#"Bars & Restaurants 1" forKey:#"title"];
[arrayLocation addObject:dict];
dict = nil;
dict = [[NSMutableDictionary alloc]init];
[dict setValue:#"32.784526" forKey:#"latitude"];
[dict setValue:#"-117.240985" forKey:#"longitude"];
[dict setValue:#"Bars & Restaurants 2" forKey:#"title"];
[arrayLocation addObject:dict];
dict = nil;
dict = [[NSMutableDictionary alloc]init];
[dict setValue:#"32.773477" forKey:#"latitude"];
[dict setValue:#"-117.241144" forKey:#"longitude"];
[dict setValue:#"Bars & Restaurants 3" forKey:#"title"];
[arrayLocation addObject:dict];
dict = nil;
dict = [[NSMutableDictionary alloc]init];
[dict setValue:#"32.775301" forKey:#"latitude"];
[dict setValue:#"-117.238893" forKey:#"longitude"];
[dict setValue:#"Bars & Restaurants 4" forKey:#"title"];
[arrayLocation addObject:dict];
dict = nil;
for(int i=0;i<[arrayLocation count];i++)
{
CLLocationCoordinate2D location;
location.latitude = [[[arrayLocation objectAtIndex:i] objectForKey:#"latitude"] doubleValue];
location.longitude = [[[arrayLocation objectAtIndex:i] objectForKey:#"longitude"] doubleValue];
MapViewAnnotation *newAnnotation = [[MapViewAnnotation alloc] initWithTitle:[[arrayLocation objectAtIndex:i] objectForKey:#"title"] Coordinate:location andIndex:i];
[arrAnnotations addObject:newAnnotation];
}
[mapView addAnnotations:arrAnnotations];
mapView.region = [MapViewAnnotation regionForAnnotations:arrAnnotations];
}
- (MKAnnotationView *)mapView:(MKMapView *)map viewForAnnotation:(id <MKAnnotation>)annotation
{
if (annotation == mapView.userLocation)
{
return nil;
}
MKPinAnnotationView *pin = (MKPinAnnotationView *) [mapView dequeueReusableAnnotationViewWithIdentifier: #"restMap"];
if (pin == nil)
{
pin = [[MKPinAnnotationView alloc] initWithAnnotation: annotation reuseIdentifier: #"restMap"];
}
else
{
pin.annotation = annotation;
}
pin.pinColor = MKPinAnnotationColorRed;
pin.animatesDrop = NO;
pin.canShowCallout=TRUE;
UIButton *btn=[UIButton buttonWithType:UIButtonTypeDetailDisclosure];
MapViewAnnotation *temp = (MapViewAnnotation *)pin.annotation;
btn.tag=temp.index;
pin.rightCalloutAccessoryView=btn;
[btn addTarget:self action:#selector(openDetail:) forControlEvents:UIControlEventTouchUpInside];
return pin;
}
#end
Implementation of MapViewAnnotation class
#import <MapKit/MapKit.h>
#interface MapViewAnnotation : NSObject <MKAnnotation , MKMapViewDelegate>{
NSString *title;
int index;
CLLocationCoordinate2D coordinate;
}
#property (nonatomic, copy) NSString *title;
#property (nonatomic, readwrite) int index;
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
- (id)initWithTitle:(NSString *)ttl andCoordinate:(CLLocationCoordinate2D)c2d;
- (id)initWithTitle:(NSString *)ttl Coordinate:(CLLocationCoordinate2D)c2d andIndex:(int)intIndex;
+(MKCoordinateRegion) regionForAnnotations:(NSArray*) annotations ;
#end
#import "MapViewAnnotation.h"
#implementation MapViewAnnotation
#synthesize title, coordinate,index;
- (id)initWithTitle:(NSString *)ttl andCoordinate:(CLLocationCoordinate2D)c2d {
self = [super init];
title = ttl;
coordinate = c2d;
return self;
}
- (id)initWithTitle:(NSString *)ttl Coordinate:(CLLocationCoordinate2D)c2d andIndex:(int)intIndex
{
self = [super init];
title = ttl;
coordinate = c2d;
index = intIndex;
return self;
}
+(MKCoordinateRegion) regionForAnnotations:(NSArray*) annotations
{
NSAssert(annotations!=nil, #"annotations was nil");
NSAssert([annotations count]!=0, #"annotations was empty");
double minLat=360.0f, maxLat=-360.0f;
double minLon=360.0f, maxLon=-360.0f;
for (id<MKAnnotation> vu in annotations) {
if ( vu.coordinate.latitude < minLat ) minLat = vu.coordinate.latitude;
if ( vu.coordinate.latitude > maxLat ) maxLat = vu.coordinate.latitude;
if ( vu.coordinate.longitude < minLon ) minLon = vu.coordinate.longitude;
if ( vu.coordinate.longitude > maxLon ) maxLon = vu.coordinate.longitude;
}
CLLocationCoordinate2D center = CLLocationCoordinate2DMake((minLat+maxLat)/2.0, (minLon+maxLon)/2.0);
MKCoordinateSpan span = MKCoordinateSpanMake(maxLat-minLat, maxLon-minLon);
MKCoordinateRegion region = MKCoordinateRegionMake (center, span);
return region;
}
#end
If anyone is looking for a Swift 3 solution, I've written this quick extension that works very well for me :)
public extension MKMapView {
public static func visibleRect(for coords: [CLLocationCoordinate2D]) -> MKMapRect {
return coords.reduce(MKMapRectNull) { outRect, coord in
let point = MKMapPointForCoordinate(coord)
let rect = MKMapRectMake(point.x, point.y, 0.1, 0.1)
let union = MKMapRectUnion(rect, outRect)
return union
}
}
public func fitCoordinates(_ coords: [CLLocationCoordinate2D],
animated: Bool = true,
insets: UIEdgeInsets = UIEdgeInsets(top: 25, left: 25, bottom: 25, right: 25)) {
let rect = MKMapView.visibleRect(for: coords)
self.setVisibleMapRect(rect, edgePadding: insets, animated: animated)
}
}
Which allows to quickly do:
map.fitCoordinates([userLocation, location1, location2])
Hope this helps anyone!
Gist here: https://gist.github.com/freak4pc/1748322a1b8bba23b6de3f47cb00c3ea
try like this may be it helps you,
MKCoordinateSpan span = MKCoordinateSpanMake(52.0f,80.0001f);
CLLocationCoordinate2D coordinate = {8.9999, 18.2812};
MKCoordinateRegion region = {coordinate, span};
MKCoordinateRegion regionThatFits = [self.mapView regionThatFits:region];
NSLog(#"Fit Region %f %f", regionThatFits.center.latitude, regionThatFits.center.longitude);
[self.mapView setRegion:regionThatFits animated:YES];
replace your coordinates and all the values respectively.
For Show All Annotation use this method, i Used this Method in same issue as your. it worked for me.
-(void)zoomToFitMapAnnotations:(MKMapView*)mapView
{
if([mapView.annotations count] == 0)
return;
CLLocationCoordinate2D topLeftCoord;
topLeftCoord.latitude = -90;
topLeftCoord.longitude = 180;
CLLocationCoordinate2D bottomRightCoord;
bottomRightCoord.latitude = 90;
bottomRightCoord.longitude = -180;
for(MYAnnotation* annotation in mapView.annotations)// here MYAnnotation is custom annotation call.
{
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);
}
NSLog(#"A%f, B%f, C%f, D%f,", topLeftCoord.latitude, topLeftCoord.longitude, bottomRightCoord.latitude, bottomRightCoord.longitude);
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;
region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.1;
region = [mapView regionThatFits:region];
[mapView setRegion:region animated:YES];
}
call this method after set all Place(Annotation) on Map View, such like..
[self zoomToFitMapAnnotations:self.mapView];

Finding Path/Route Between two points on MapKit in iPhone

I am trying to find the path between two locations on Mapkit. All I have is two locations. Now I have to find the exact path between these points and draw a line between these points using MapKit. I have gone through several examples in which they are using .csv files. In that .csv file they have stored the latitude and longitude values of the full path and drawing line based on those values.
But here I am trying to draw a line without knowing the path. So is there any way to find the path dynamically and draw a line?
Below is the code to finds path & draws line between two locations.
To implement below class:
_mapRecord = [[PSMapDirection alloc] initWithFrame:CGRectMake(0.0, 49.0, 320.0, 411.0)];
[self.view addSubview:_mapRecord];
MapDirection.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "RegexKitLite.h"
#interface MapDirection : UIView<MKMapViewDelegate>
{
MKMapView* mapView;
NSArray* routes;
BOOL isUpdatingRoutes;
}
-(void) showRouteFrom: (MKAnnotation*) f to:(MKAnnotation*) t;
#end
MapDirection.m
#import "MapDirection.h"
#interface MapDirection()
-(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) from to: (CLLocationCoordinate2D) to;
-(void) centerMap;
#end
- (id) initWithFrame:(CGRect) frame
{
self = [super initWithFrame:frame];
if (self != nil)
{
mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
mapView.showsUserLocation = NO;
[mapView setDelegate:self];
[self addSubview:mapView];
}
return self;
}
- (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;
}
-(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) f to: (CLLocationCoordinate2D) t
{
NSString* saddr = [NSString stringWithFormat:#"%f,%f", f.latitude, f.longitude];
NSString* daddr = [NSString stringWithFormat:#"%f,%f", t.latitude, t.longitude];
NSString* apiUrlStr = [NSString stringWithFormat:#"http://maps.google.com/maps?output=dragdir&saddr=%#&daddr=%#", saddr, daddr];
NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
//NSLog(#"api url: %#", apiUrl);
NSError* error = nil;
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSASCIIStringEncoding error:&error];
NSString *encodedPoints = [apiResponse stringByMatching:#"points:\\\"([^\\\"]*)\\\"" capture:1L];
return [self decodePolyLine:[encodedPoints mutableCopy]];
}
-(void) centerMap
{
MKCoordinateRegion region;
CLLocationDegrees maxLat = -90.0;
CLLocationDegrees maxLon = -180.0;
CLLocationDegrees minLat = 90.0;
CLLocationDegrees minLon = 180.0;
for(int idx = 0; idx < routes.count; idx++)
{
CLLocation* currentLocation = [routes objectAtIndex:idx];
if(currentLocation.coordinate.latitude > maxLat)
maxLat = currentLocation.coordinate.latitude;
if(currentLocation.coordinate.latitude < minLat)
minLat = currentLocation.coordinate.latitude;
if(currentLocation.coordinate.longitude > maxLon)
maxLon = currentLocation.coordinate.longitude;
if(currentLocation.coordinate.longitude < minLon)
minLon = currentLocation.coordinate.longitude;
}
region.center.latitude = (maxLat + minLat) / 2.0;
region.center.longitude = (maxLon + minLon) / 2.0;
region.span.latitudeDelta = 0.01;
region.span.longitudeDelta = 0.01;
region.span.latitudeDelta = ((maxLat - minLat)<0.0)?100.0:(maxLat - minLat);
region.span.longitudeDelta = ((maxLon - minLon)<0.0)?100.0:(maxLon - minLon);
[mapView setRegion:region animated:YES];
}
-(void) showRouteFrom: (MKAnnotation*) f to:(MKAnnotation*) t
{
if(routes)
{
[mapView removeAnnotations:[mapView annotations]];
}
[mapView addAnnotation:f];
[mapView addAnnotation:t];
routes = [self calculateRoutesFrom:f.coordinate to:t.coordinate];
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];
[mapView addOverlay:polyLine];
[self centerMap];
}
#pragma mark MKPolyline delegate functions
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:overlay];
polylineView.strokeColor = [UIColor purpleColor];
polylineView.lineWidth = 5.0;
return polylineView;
}
#end
Sample Map Route for starting points - "41.967659,-87.627869" and destination points - "41.574361,-91.083069"
Here The way in which I am able to draw direction between two points(Location).
First of all download GoogleMap sdk from this link and integrate into your application.
Now API key required and you can create as par given guidelines on this link.
Below are Code that draw direction on google map between two location.
-(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) f to: (CLLocationCoordinate2D) t {
NSString* saddr = [NSString stringWithFormat:#"%f,%f", f.latitude, f.longitude];
NSString* daddr = [NSString stringWithFormat:#"%f,%f", t.latitude, t.longitude];
NSURL *url=[NSURL URLWithString:[NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%#&destination=%#&sensor=false&avoid=highways&mode=driving",saddr,daddr]];
NSError *error=nil;
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init] ;
[request setURL:url];
[request setHTTPMethod:#"POST"];
NSURLResponse *response = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error: &error];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSDictionary * dic = [NSJSONSerialization JSONObjectWithData:[responseString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONWritingPrettyPrinted error:nil];
return [self decodePolyLine:[self parseResponse:dic]];
}
- (NSString *)parseResponse:(NSDictionary *)response {
NSArray *routes = [response objectForKey:#"routes"];
NSDictionary *route = [routes lastObject];
if (route) {
NSString *overviewPolyline = [[route objectForKey:
#"overview_polyline"] objectForKey:#"points"];
return overviewPolyline;
}
return #"";
}
-(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;
}
- (void)loadMapViewWithDirection {
float lat = 23.050671;
float lng = 72.541351;
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:lat
longitude:lng
zoom:10];
GMSMapView * mapView = [GMSMapView mapWithFrame:CGRectMake(0, 75, 320, self.view.frame.size.height-kHeaderRect.size.height) camera:camera];
self.mapView.myLocationEnabled = YES;
float sourceLatitude = 23.050671;
float sourceLongitude = 72.541351;
float destLatitude = 23.036138;
float destLongitude = 72.603836;
GMSMarker *sourceMarker = [[GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake(sourceLatitude, sourceLongitude);
marker.map = self.mapView;
GMSMarker *destMarker = [[GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake(destLatitude, destLongitude);
marker.map = self.mapView;
self.mapView.delegate = self;
[self drawDirection:CLLocationCoordinate2DMake(sourceLatitude, sourceLongitude) and:CLLocationCoordinate2DMake(destLatitude, destLongitude)];
[self.view addSubview:self.mapView];
}
- (void) drawDirection:(CLLocationCoordinate2D)source and:(CLLocationCoordinate2D) dest {
GMSPolyline *polyline = [[GMSPolyline alloc] init];
GMSMutablePath *path = [GMSMutablePath path];
NSArray * points = [self calculateRoutesFrom:source to:dest];
NSInteger numberOfSteps = points.count;
for (NSInteger index = 0; index < numberOfSteps; index++)
{
CLLocation *location = [points objectAtIndex:index];
CLLocationCoordinate2D coordinate = location.coordinate;
[path addCoordinate:coordinate];
}
polyline.path = path;
polyline.strokeColor = [UIColor redColor];
polyline.strokeWidth = 2.f;
polyline.map = self.mapView;
// Copy the previous polyline, change its color, and mark it as geodesic.
polyline = [polyline copy];
polyline.strokeColor = [UIColor greenColor];
polyline.geodesic = YES;
polyline.map = self.mapView;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self loadMapViewWithDirection];
}
You can refer this code, it does exactly what you want.EDIT: and this also
I don't think you can do this locally. Implementing an algoritm for finding a path between two gps points requires a lot of input data (data from the maps) and you don't have this. Only a map provider can afford to implement such algoritm and expose an API for using it. I think Google have routing API, but I haven't played around with it...
https://developers.google.com/maps/documentation/directions/
Note that the TOS say that you have to display the results on a Google map, so you'll have to disable the functionality on the next iOS release

many pins, how to distinguish each pin?

Please help me, I am stuck with this MapView:
I have a MapView and a small label under that MapView. On the MapView, I have many pins (MKPinAnnotationView), I know how to set the title and subtitle of each pin by using array, but I do not know how to distinguish each pin. I mean when user taps a pin, the label will show the title of the tapped pin.
Here is some of my code:
This is where I define the pin:
#implementation PlacePin
#synthesize coordinate,title,subtitle;
#synthesize nTag;
- (id)initWithLocation:(CLLocationCoordinate2D)coord{
self = [super init];
if (self) {
coordinate = coord;
}
return self;
}
-(void)dealloc{
[title release];
[subtitle release];
[super dealloc];
}
#end
This is where I proccess the result from server:
- (void) resultCheck {
NSString *strUrl = [NSString stringWithFormat:#"ServerAddress.com"];
NSLog(#"MapView - resultCheck: url: %# ", strUrl);
NSURL *url = [ NSURL URLWithString:strUrl];
//get the result from server
NSString *result = [NSString stringWithContentsOfURL:url];
NSLog(#"MapView - resultCheck: result: %#", result);
NSDictionary *dictionary = [result JSONValue];
NSLog(#"MapView - resultCheck: dictionary: %#", dictionary);
//process the JSON, get two parameters: xPos, yPos
NSDictionary *value1 = [dictionary valueForKey:#"result"];
NSDictionary *value2 = [value1 valueForKey:#"post"];
NSArray *arrXPos = [value2 valueForKey:#"xPos"]; //array of xPos
NSArray *arrYPos = [value2 valueForKey:#"yPos"]; //array of yPos
self.arrName = [value2 valueForKey:#"name"]; //array of name
self.arrPlaceInfor = [value2 valueForKey:#"place_info"];
NSLog(#"MapView - resultCheck: value1: %#",value1);
NSLog(#"MapView - resultCheck: value2: %#",value2);
NSLog(#"MapView - resultCheck: value3: %#",arrXPos);
NSLog(#"MapView - resultCheck: value4: %#",arrYPos);
//get the xPos and yPos
for (int i = 0 ; i < [value2 count]; i++) {
//display the place depended on the xPos and yPos
CLLocationCoordinate2D location;
location.latitude = [[ NSString stringWithFormat:#"%#",[arrXPos objectAtIndex:i]] doubleValue];
location.longitude = [[ NSString stringWithFormat:#"%#",[arrYPos objectAtIndex:i]] doubleValue];
PlacePin *mapPoint = [[PlacePin alloc] initWithLocation:location];
//set the title and subtitle of the pin depending on the result from server
mapPoint.title = [ NSString stringWithFormat:#"%#",[self.arrName objectAtIndex:i]];
mapPoint.subtitle = [ NSString stringWithFormat:#"%#",[self.arrPlaceInfor objectAtIndex:i]];
[mapView addAnnotation:mapPoint];
[mapPoint release];
mapPoint = nil;
}
}
This is where I proccess the pin and set the label - where I am getting stuck :(
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view NS_AVAILABLE(NA, 4_0){
self.labelShortIntro.text = #"1111111111111";
}
//customize an annotation
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation{
MKPinAnnotationView *annView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"currentloc"];
annView.pinColor = MKPinAnnotationColorPurple;
annView.animatesDrop = TRUE;
annView.canShowCallout = YES;
annView.calloutOffset = CGPointMake(-5, 5);
return annView;
}
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{
PlacePin *selectedPin = view.annotation;
NSLog(#"Title = %# Subtitle = %#",selectedPin.title,selectedPin.subtitle);
self.labelShortIntro.text = [NSString stringWithFormat:#"Title = %# Subtitle = %#",selectedPin.title,selectedPin.subtitle];
}
in didSelectAnnotationView delegate:
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
NSArray *selectedAnnotations = mapView.selectedAnnotations;
for(PlacePin *ann in selectedAnnotations)
{
NSLog(#"%#",ann.title);
self.labelShortIntro.text=ann.title;
}
}
I hope this code will help you.

viewForOverlay is not getting called

I want to draw route between two path on map in ios. The problem is that the mapView:viewforoverlay is no getting called.
Here is my code complete code. There is no problem in parsing as i have tested it using the NSLog statement. I have customized the code from here : http://spitzkoff.com/craig/?p=136
Thanks to this website. bt please help me out.
#import "AppViewController.h"
#import "XMLParser.h"
#import "AppAppDelegate.h"
#interface AppViewController ()
#end
#implementation AppViewController
#synthesize mapview= _mapview;
#synthesize routeLine = _routeLine;
#synthesize routeLineView = _routeLineView;
#synthesize coordinatearray = _coordinatearray;
#synthesize pathlatandlong = _pathlatandlong;
#synthesize coordinate = _coordinate;
- (void)viewDidLoad
{
[super viewDidLoad];
[self doParse];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setMapview:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
-(void)doParse
{
[_coordinatearray removeAllObjects];
NSURL *parseurl = [[NSURL alloc] initWithString:#"https://maps.google.com/maps?f=d&hl=en&saddr=19.055229,72.830829&daddr=19.113611,72.871389&ie=UTF8&om=0&output=kml"];
NSXMLParser *nsxmlparser = [[NSXMLParser alloc] initWithContentsOfURL:parseurl];
XMLParser *parser = [[XMLParser alloc] initXMLParser];
[nsxmlparser setDelegate:parser];
BOOL success = [nsxmlparser parse];
if(success)
{
[self loadRoute];
if (nil != self.routeLine)
{
[self.mapview addOverlay:self.routeLine];
}
// zoom in on the route.
[self zoomInOnRoute];
}
}
-(void) loadRoute
{
AppAppDelegate *obj = (AppAppDelegate*)[[UIApplication sharedApplication] delegate];
NSArray* pointStrings = [obj.parsedxmldata componentsSeparatedByString:#" "];
// while we create the route points, we will also be calculating the bounding box of our route
// so we can easily zoom in on it.
MKMapPoint northEastPoint;
MKMapPoint southWestPoint;
// create a c array of points.
MKMapPoint* pointArr = malloc(sizeof(CLLocationCoordinate2D) * pointStrings.count);
for(int idx = 0; idx < pointStrings.count-1; idx++)
{
// break the string down even further to latitude and longitude fields.
NSString* currentPointString = [pointStrings objectAtIndex:idx];
NSArray* latLonArr = [currentPointString componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#","]];
CLLocationDegrees latitude = [[latLonArr objectAtIndex:1] doubleValue];
CLLocationDegrees longitude = [[latLonArr objectAtIndex:0] doubleValue];
NSLog(#"%f %f" , latitude , longitude);
// create our coordinate and add it to the correct spot in the array
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude);
MKMapPoint point = MKMapPointForCoordinate(coordinate);
//
// adjust the bounding box
//
// if it is the first point, just use them, since we have nothing to compare to yet.
if (idx == 0)
{
northEastPoint = point;
southWestPoint = point;
}
else
{
if (point.x > northEastPoint.x)
northEastPoint.x = point.x;
if(point.y > northEastPoint.y)
northEastPoint.y = point.y;
if (point.x < southWestPoint.x)
southWestPoint.x = point.x;
if (point.y < southWestPoint.y)
southWestPoint.y = point.y;
}
pointArr[idx] = point;
}
// create the polyline based on the array of points.
self.routeLine = [MKPolyline polylineWithPoints:pointArr count:pointStrings.count];
_routeRect = MKMapRectMake(southWestPoint.x, southWestPoint.y, northEastPoint.x - southWestPoint.x, northEastPoint.y - southWestPoint.y);
}
-(void) zoomInOnRoute
{
[self.mapview setVisibleMapRect:_routeRect];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
}
- (void)dealloc
{
self.mapview = nil;
self.routeLine = nil;
self.routeLineView = nil;
}
- (MKOverlayView *)mapView:(MKMapView *)map viewForOverlay:(id <MKOverlay>)overlay
{
MKOverlayView* overlayView = nil;
NSLog(#"Inside viewforoverlay");
if(overlay == self.routeLine)
{
//if we have not yet created an overlay view for this overlay, create it now.
if(nil == self.routeLineView)
{
self.routeLineView = [[MKPolylineView alloc] initWithPolyline:self.routeLine];
self.routeLineView.fillColor = [UIColor redColor];
self.routeLineView.strokeColor = [UIColor redColor];
self.routeLineView.lineWidth = 3;
}
overlayView = self.routeLineView;
}
return overlayView;
}
#end
Make sure the delegate for the mapView is set to your controller, either in the XIB or programmatically as follows:
- (void)viewDidLoad
{
[super viewDidLoad];
[_mapview setDelegate:self];
[self doParse];
// Do any additional setup after loading the view, typically from a nib.
}

how to draw line between two points?

i want to draw line between two points in my view how it possible.?
Edit:ya thax.i have got solution. Line draw perfectly.I want to draw multiple line with different points.I am using for loop and every rotaion i pass the start and end points.but only last point is drawn.how to solve this problem?
You need to use a few CoreGraphics functions:
// get the current context
CGContextRef context = UIGraphicsGetCurrentContext();
// set the stroke color and width
CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 1.0);
CGContextSetLineWidth(context, 2.0);
// move to your first point
CGContextMoveToPoint(context, 10.0, 10.0);
// add a line to your second point
CGContextAddLineToPoint(context, 50.0, 10.0);
// tell the context to draw the stroked line
CGContextStrokePath(context);
This example would draw a horizontal white line with a thickness of 2. Apple has some great sample code and tutorials including the QuartzDemo tutorial: http://developer.apple.com/iPhone/library/samplecode/QuartzDemo/index.html.
The QuartzDemo application has great examples of how to use CoreGraphics, including lines and bezier curves. download here
Take a look at QuartzLineDrawing.m in the sample code. You'll be able to find some great examples there :-)
Since this is 09' answers and whatnot I figure I update the link and code here for anyone looking in 11'.
The link for the Quartz Demo is: http://developer.apple.com/library/ios/#samplecode/QuartzDemo/Introduction/Intro.html
and the code I use to draw multiple lines is:
//Drawing lines
// Set the color that we want to use to draw the line
[ [ UIColor brownColor] set];
//Get the current graphics context (pen)
CGContextRef currentContext = UIGraphicsGetCurrentContext();
// Set the width for the line
CGContextSetLineWidth(currentContext,
5.0f);
// Start the line at this point
CGContextMoveToPoint(currentContext,
20.0f,
20.0f);
// And end it at this point
CGContextAddLineToPoint(currentContext,
100.0f,
100.0f);
// Extend the line to another point
CGContextAddLineToPoint(currentContext,
300.0f,
100.0f);
//Use the context's current color to draw the line
CGContextStrokePath(currentContext);
I recommend reading Graphics and Animation on iOS: A Beginner's Guide to Core Graphics and Core Animation by Vandad Nahavandipoor. It's mostly on graphics than animation though. I recommend checking out his videos on animation if your interested. http://www.youtube.com/watch?v=ybMFPB-Gbsw&feature=player_embedded They're called Animations in iOS using Block Objects Part I and II. Supposedly there are supposed to be more videos at some point. But the videos go with the book.
That's it.
func locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation)
{
let CurrentLogitude = String(format: "%.8f", newLocation.coordinate.longitude)
//print(CurrentLogitude)
let CurrentLatitude = String(format: "%.8f", newLocation.coordinate.latitude)
// print(CurrentLatitude)
//[self.locationManager stopUpdatingLocation];
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError)
{
}
func locationManager(manager: CLLocationManager,
didChangeAuthorizationStatus status: CLAuthorizationStatus)
{
var shouldIAllow = false
var locationStatus :String
switch status
{
case CLAuthorizationStatus.Restricted:
locationStatus = "Restricted Access to location"
case CLAuthorizationStatus.Denied:
locationStatus = "User denied access to location"
case CLAuthorizationStatus.NotDetermined:
locationStatus = "Status not determined"
default:
locationStatus = "Allowed to location Access"
shouldIAllow = true
}
NSNotificationCenter.defaultCenter().postNotificationName("LabelHasbeenUpdated", object: nil)
if (shouldIAllow == true)
{
NSLog("Location to Allowed")
// Start location services
locationManager.startUpdatingLocation()
} else {
NSLog("Denied access: \(locationStatus)")
}
}
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView?
{
let pin = MKAnnotationView(annotation: annotation, reuseIdentifier: "locationpin")
pin.image = UIImage(named: "locationpin.png")
let notationView: UIView = UIView()
notationView.frame = CGRectMake(0, 0, 400, 300)
notationView.backgroundColor = UIColor.grayColor()
pin.leftCalloutAccessoryView = notationView
pin.canShowCallout = true
return pin
}
#pragma mark - Mapview Delegate Method
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
MKPinAnnotationView *pin = (MKPinAnnotationView *) [self.mapView dequeueReusableAnnotationViewWithIdentifier: #"id"];
if (!pin && ![annotation isKindOfClass:[MKUserLocation class]])
{
pin = [[MKPinAnnotationView alloc] initWithAnnotation: annotation reuseIdentifier: #"id"] ;
pin.pinTintColor=[UIColor blueColor];
pin.canShowCallout = true;
}
else
{
if (pin == nil)
{
pin = [[MKPinAnnotationView alloc] initWithAnnotation: annotation reuseIdentifier: #"id"] ;
}
else
{
pin.annotation = annotation;
}
pin.pinTintColor=[UIColor grayColor];
UIView *notationView=[[UIView alloc]init];
notationView.frame=CGRectMake(0, 0, 320, 300);
notationView.backgroundColor = [UIColor grayColor];
UILabel *lbl=[[UILabel alloc]init];
lbl.frame=CGRectMake(5, 5, 300, 25);
lbl.text=#"Current Location";
lbl.textColor=[UIColor whiteColor];
[notationView addSubview:lbl];
UIImageView *img=[[UIImageView alloc]init];
img.frame=CGRectMake(0, 0, 50,50);
img.image=[UIImage imageNamed:#"ios.png"];
// pin.leftCalloutAccessoryView = notationView;
// pin.rightCalloutAccessoryView = img;
//pin.detailCalloutAccessoryView=customView;
pin.animatesDrop = true;
pin.canShowCallout = true;
}
return pin;
}
-(IBAction)btnRoutePathClicked:(id)sender
{
[self.mapView removeAnnotation:point];
[self.mapView removeOverlay:polyline];
[self.mapView reloadInputViews];
MKCoordinateSpan span = MKCoordinateSpanMake(1.0, 1.0);
MKCoordinateRegion region = MKCoordinateRegionMake(currentLocation.coordinate, span);
[self.mapView setRegion:region];
[self.mapView setCenterCoordinate:currentLocation.coordinate animated:YES];
NSString *baseUrl = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%#&destination=%#&sensor=true",[NSString stringWithFormat:#"%f,%f",currentLocation.coordinate.latitude,currentLocation.coordinate.longitude],[NSString stringWithFormat:#"22.45,72.4545"]];
//http://maps.googleapis.com/maps/api/directions/json?origin=51.194400,4.475816&destination=50.941278,6.958281&sensor=true
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"];
if ([routes count]==0)
{
NSLog(#"Routs:=>%#",routes);
}
else
{
NSDictionary *firstRoute = [routes objectAtIndex:0];
NSDictionary *leg = [[firstRoute objectForKey:#"legs"] objectAtIndex:0];
NSDictionary *end_location = [leg objectForKey:#"end_location"];
double latitudes = [[end_location objectForKey:#"lat"] doubleValue];
double longitudes = [[end_location objectForKey:#"lng"] doubleValue];
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitudes, longitudes);
point = [[MKPointAnnotation alloc] init];
point.coordinate = coordinate;
point.title = [leg objectForKey:#"end_address"];
[self.mapView addAnnotation:point];
NSDictionary *route = [routes lastObject];
if (route)
{
NSString *overviewPolyline = [[route objectForKey: #"overview_polyline"] objectForKey:#"points"];
NSMutableArray *_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];
}
}
}];
}
-(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 *latitudes = [[NSNumber alloc] initWithFloat:lat * 1e-5];
NSNumber *longitudes = [[NSNumber alloc] initWithFloat:lng * 1e-5];
CLLocation *location = [[CLLocation alloc] initWithLatitude:[latitudes floatValue] longitude:[longitudes floatValue]];
[array addObject:location];
}
return array;
}
- (MKPolylineRenderer *)mapView:(MKMapView *)mapView viewForOverlay:(id)overlay{
MKPolylineRenderer *polylineView = [[MKPolylineRenderer alloc] initWithPolyline:overlay];
polylineView.strokeColor = [UIColor redColor];
polylineView.lineWidth = 4.0;
polylineView.alpha = 0.5;
return polylineView;
}