Detect zoom on GMSMapView (iOS) - ios

How can I find if the user zoomed in/out on my mapView (GMSMapView)?
I want to do that if the zoom is bigger than 14 all the markers on the map will disappear and if it's smaller all the markers will reload.
How can I do that?
Thanks!

The below code assumes that the view controller has a property of "markerArray" which holds all of the markers.
-(void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition*)position {
int zoom= mapView.camera.zoom;
if (zoom < 14) {
[mapView_ clear];
}
else{
[self displayAllMarkers];
}
}
-(void) displayAllMarkers{
for (BarObject *barMarker in markerArray){
GMSMarker *marker = [[GMSMarker alloc] init];
marker.position = barMarker.location; //
marker.icon = [GMSMarker markerImageWithColor:[UIColor blackColor]];
marker.map = mapView_;
}
}

I also searched for this answer over the summer, and here is what I found and ended up doing:
Create a category on MKMapView:
I named it MKMapView+ZoomLevel
.h
// MKMapView+ZoomLevel.h
#import <MapKit/MapKit.h>
#interface MKMapView (ZoomLevel)
- (int)currentZoomLevel;
#end
.m
// MKMapView+ZoomLevel.m
#import "MKMapView+ZoomLevel.h"
#define MERCATOR_OFFSET 268435456
#define MERCATOR_RADIUS 85445659.44705395
#define MAX_GOOGLE_LEVELS 20
#implementation MKMapView (ZoomLevel)
- (int)currentZoomLevel
{
CLLocationDegrees longitudeDelta = self.region.span.longitudeDelta;
CGFloat mapWidthInPixels = self.bounds.size.width*2;//2 is for retina display
double zoomScale = longitudeDelta * MERCATOR_RADIUS * M_PI / (180.0 * mapWidthInPixels);
double zoomer = MAX_GOOGLE_LEVELS - log2( zoomScale );
if ( zoomer < 0 ) zoomer = 0;
zoomer = round(zoomer);
return (int)zoomer;
}
#end
Then in your view controller:
#import "MKMapView+ZoomLevel.h
// insert logic here
double zoomLevel = [self.mapView currentZoomLevel];
if (zoomLevel > 14 ) {
// add code to hide or resize your annotations
for (id<MKAnnotation> annotation in self.mapView.annotations) {
if (![annotation isKindOfClass:[MKUserLocation class]]) {
[self.mapView removeAnnotation:annotation];
}
}
}

Related

overlay map view not showing up

I'm trying to make a MKMapView and add and overlay to it using coordinates.
It is not showing up in the mapView.
it seems to be compiling ok but when I open the mapView view in the storyboard I see the map of the world but there is no red overlay anywhere.
Here is my code.
my header
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreMotion/CoreMotion.h>
#import <MapKit/MapKit.h>
NS_ASSUME_NONNULL_BEGIN
#interface mapViewController : UIViewController<CLLocationManagerDelegate,MKMapViewDelegate>
#property (nonatomic, retain) IBOutlet MKMapView *mapView;
#property(nonatomic, retain) MKPolygon *polygon;
#end
and my .m file
#import "mapViewController.h"
#interface mapViewController ()
#end
#implementation mapViewController
#synthesize mapView,locationManager,polygon;
- (void)viewDidLoad {
[super viewDidLoad];
mapView.delegate = self;
NSDictionary *d1=[NSDictionary dictionaryWithObjectsAndKeys:#"37.57111111",#"x",#"-109.52166667",#"y",nil];
NSDictionary *d2=[NSDictionary dictionaryWithObjectsAndKeys:#"32.01138889",#"x",#"-109.59000000",#"y",nil];
NSDictionary *d3=[NSDictionary dictionaryWithObjectsAndKeys:#"31.83166667",#"x",#"-111.95416667",#"y",nil];
NSDictionary *d4=[NSDictionary dictionaryWithObjectsAndKeys:#"32.34250000",#"x",#"-115.14333333",#"y",nil];
NSDictionary *d5=[NSDictionary dictionaryWithObjectsAndKeys:#"34.89722222",#"x",#"-115.47611111",#"y",nil];
NSDictionary *d6=[NSDictionary dictionaryWithObjectsAndKeys:#"37.32083333",#"x",#"-116.02027778",#"y",nil];
NSDictionary *d7=[NSDictionary dictionaryWithObjectsAndKeys:#"37.53305556",#"x",#"-114.73416667",#"y",nil];
NSDictionary *d8=[NSDictionary dictionaryWithObjectsAndKeys:#"37.53166667",#"x",#"-114.11277778",#"y",nil];
NSDictionary *d9=[NSDictionary dictionaryWithObjectsAndKeys:#"37.57111111",#"x",#"-109.52166667",#"y",nil];
NSArray *azcoord = [NSArray arrayWithObjects:d1,d2,d3,d4,d5,d6,d7,d8, nil];
CLLocationCoordinate2D coordinates[azcoord.count];
int coordinatesIndex = 0;
for (NSDictionary * c in azcoord) {
double x = [[c valueForKey:#"x"] doubleValue];
double y = [[c valueForKey:#"y"] doubleValue];
CLLocationCoordinate2D coordinate;
coordinate.latitude = y;
coordinate.longitude = x;
//Put this coordinate in the C array...
coordinates[coordinatesIndex] = coordinate;
coordinatesIndex++;
}
polygon = [MKPolygon polygonWithCoordinates:coordinates count:azcoord.count];
[self.mapView addOverlay:polygon];
}
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
{
MKPolygonRenderer *renderer = [[MKPolygonRenderer alloc] initWithPolygon:polygon];
renderer.fillColor = [[UIColor redColor] colorWithAlphaComponent:1];
renderer.strokeColor = [[UIColor blackColor] colorWithAlphaComponent:0.7];
renderer.lineWidth = 2;
return renderer;
}
#end
what I am trying to do is draw an overlay for the state of Arizona. I've checked the coordinates and they are correct.
Eventually I want to create overlays for all states.
can anyone see where I'm going wrong?
I figured it out by changing my approach. Here is my code that is working.
first i create a CLLocationCoordinate2D array of my coordinates and make them into a polygon. then add to mapView.
CLLocationCoordinate2D points[7];
points [0] = CLLocationCoordinate2DMake(36.99910000, -109.04520000);
points [1] = CLLocationCoordinate2DMake(31.33460000, -109.05220000);
points [2] = CLLocationCoordinate2DMake(31.33700000, -111.07720000);
points [3] = CLLocationCoordinate2DMake(32.49410000, -114.81360000);
points [4] = CLLocationCoordinate2DMake(36.10660000, -114.75180000);
points [5] = CLLocationCoordinate2DMake(36.21600000, -114.03940000);
points [6] = CLLocationCoordinate2DMake(37.00150000, -114.04820000);
polygon = [MKPolygon polygonWithCoordinates:points count:7];
[self.mapView addOverlay:polygon];
then I render that to the map view.
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
{ NSLog(#"YES!!!!!!!!!!!!!!!!!");
MKPolygonRenderer *renderer = [[MKPolygonRenderer alloc] initWithPolygon:polygon];
renderer.fillColor = [[UIColor redColor] colorWithAlphaComponent:0.2];
renderer.strokeColor = [[UIColor blackColor] colorWithAlphaComponent:0.7];
renderer.lineWidth = 1;
return renderer;
}
then I check to see if my location is inside the polygon.
CLLocationCoordinate2D sampleLocation = CLLocationCoordinate2DMake(myLatitude,myLongitude);//13,80 is the latlong of clear colored area of the MKPolygon in the below image.
MKMapPoint mapPoint = MKMapPointForCoordinate(sampleLocation);
CGPoint mapPointAsCGP = CGPointMake(mapPoint.x, mapPoint.y);
for (id<MKOverlay> polygon in mapView.overlays) {
if([polygon isKindOfClass:[MKPolygon class]]){
NSLog(#"YES<<<<<<<<<<<<<<<<<<");
MKPolygon *polygons = (MKPolygon*) polygon;
CGMutablePathRef mpr = CGPathCreateMutable();
MKMapPoint *polygonPoints = polygons.points;
for (int p=0; p < polygons.pointCount; p++){
MKMapPoint mp = polygonPoints[p];
if (p == 0)
CGPathMoveToPoint(mpr, NULL, mp.x, mp.y);
else
CGPathAddLineToPoint(mpr, NULL, mp.x, mp.y);
}
if(CGPathContainsPoint(mpr , NULL, mapPointAsCGP, TRUE)){
NSLog(#"YES?????????????????????????????????");
//do something else
}
CGPathRelease(mpr);
}
}
I at first didn't want to add a map view but then decided I need to and now that I have I like it.

How to move marker on the Google Map like Ola app

I am working on app the like Ola cabs. When the user drags map the a view transparent view appears with marker moving and when the user stops dragging the we have to centre the gmscamera position same like ola cab app. This the image when the map is not dragged.
after dragging I am getting the location using the below code.
- (void) mapView:(GMSMapView *)mapView idleAtCameraPosition:(GMSCameraPosition *)position {
latitude = mapView.camera.target.latitude;
longitude = mapView.camera.target.longitude;
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(latitude, longitude);
[self hourelywebsevice:updatedlogintokenstring withlat:latitude withlong:longitude withcoustamerid:updatednamestring];
// [self hourelywebsevice:#"abc" withlat:latitude withlong:longitude];
marker.position = center;
}
Now my problem is how create second screen.
I have achieved this kind of things in two apps which are related with live tracking of vahicle.
There are some requirements that I have used:
App having Always location usage permission with proper battery usage message.
Used Socket connection on both end. Driver & Customer. For that Socket.io is used. Same is configured in Web.
Trigged location service at every 2 sec, so that I can handle battery usage.
Every 2 sec, send data to socket and socket listener can use that data to show car on map.
Car icon in 90 degree rotate(car indicate to move on right side)
Most important thing is that Driver latitude and longitude should with correct for showing car movement on the map. gmsMarker location consider as old value and newLocation value is current location.
let preLoc = CLLocation.init(latitude: self.gmsMarker.position.latitude, longitude: self.gmsMarker.position.longitude)
let curLoc = CLLocation.init(latitude: newLocation.latitude, longitude: newLocation.longitude)
let changeInLocation = preLoc.distance(from: curLoc)
if changeInLocation > 5{
let degree = self.DegreeBearing(preLoc, curLoc)
if degree > 5{
self.gmsMarker.rotation = degree
}
}
Below four function will calculate your travel direction and based on that car will show correct on road with moving.
func DegreeBearing(_ A:CLLocation,_ B:CLLocation)-> Double{
var dlon = self.ToRad(degrees: B.coordinate.longitude - A.coordinate.longitude)
let dPhi = log(tan(self.ToRad(degrees: B.coordinate.latitude) / 2 + M_PI / 4) / tan(self.ToRad(degrees: A.coordinate.latitude) / 2 + M_PI / 4))
if abs(dlon) > M_PI{
dlon = (dlon > 0) ? (dlon - 2*M_PI) : (2*M_PI + dlon)
}
return self.ToBearing(radians: atan2(dlon, dPhi))
}
func ToRad(degrees:Double) -> Double{
return degrees*(M_PI/180)
}
func ToBearing(radians:Double)-> Double{
return (ToDegrees(radians: radians) + 360).truncatingRemainder(dividingBy: 360)
}
func ToDegrees(radians:Double)->Double{
return radians * 180 / M_PI
}
For Customer side, just show marker with whatever data you received from Driver side as self.gmsMarker.rotation value.
Use delegates of GMSMapView
- (void) mapView:(GMSMapView *)mapView didDragMarker:(GMSMarker *)marker;
- (void) mapView:(GMSMapView *)mapView didBeginDraggingMarker:(GMSMarker *)marker;
- (void) mapView:(GMSMapView *)mapView didEndDraggingMarker:(GMSMarker *)marker;
#interface ViewController () <CLLocationManagerDelegate, GMSMapViewDelegate> {
GMSMarker *marker2;
}
In viewDidLoad
marker2 = [[GMSMarker alloc] init];
// Create a GMSCameraPosition that tells the map to display the
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:latitude
longitude:longitude
zoom:18];
// Create GMSMapView
GMSMapView *mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
// Available map types: kGMSTypeNormal, kGMSTypeSatellite, kGMSTypeHybrid,
// kGMSTypeTerrain, kGMSTypeNone
// Set the mapType to Satellite
mapView.mapType = kGMSTypeSatellite;
mapView.myLocationEnabled = YES;
self.view = mapView;
// Creates a marker in the center of the map.
GMSMarker *marker = [[GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake(latitude, longitude);
marker.map = mapView;
mapView.delegate = self;
After that call delegate functions
- (void)mapView:(GMSMapView *)mapView willMove:(BOOL)gesture {
// NSLog(#"willMove");
}
- (void) mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position {
// NSLog(#"didChangeCameraPosition");
// Creates a marker in the center of the map.
// NSLog(#"%#", position);
marker2.position = CLLocationCoordinate2DMake(mapView.camera.target.latitude, mapView.camera.target.longitude);
marker2.map = mapView;
// marker2.draggable = YES;
marker2.icon = [GMSMarker markerImageWithColor:[UIColor blueColor]];
}

MKMapView - How to detect zoom vs drag event [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
How to detect zoom vs drag event on MKMapView.
I want to reload the map in case users want to drag/scroll map to new position. I don't want to reload the Map with zoom in/out event.
I found a solution :(. really simple
1. keep the previous zoom level.
2. in the regionDidChangeAnimated method, get new zoom level of Map and check it with the previous level.
this is my code.
#define MERCATOR_RADIUS 85445659.44705395
#define kVerySmallValue (0.000001)
- (BOOL)compare2Double:(double)first isEqualTo:(double)second {
if(fabs(first - second) < kVerySmallValue)
return YES;
else
return NO;
}
- (double)getZoomLevel
{
static double maxGoogleLevels = -1.0;
if (maxGoogleLevels < 0.0)
maxGoogleLevels = log2(MKMapSizeWorld.width / 256.0);
CLLocationDegrees longitudeDelta = self.mapView.region.span.longitudeDelta;
CGFloat mapWidthInPixels = self.mapView.bounds.size.width;
double zoomScale = longitudeDelta * MERCATOR_RADIUS * M_PI / (180.0 * mapWidthInPixels);
double zoomer = maxGoogleLevels - log2( zoomScale );
if ( zoomer < 0 ) zoomer = 0;
NSLog(#"zoom: %f",zoomer);
return zoomer;
}
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
double newZoom = [self getZoomLevel];
if ([self compareDouble:newZoom isEqualTo:zoomLevel]) {
NSLog(#"Drag");
}else{
zoomLevel = newZoom;
NSLog(#"Zoom");
}
}
You can find out through the below methods of PangestureRecognizer
- (void)viewDidLoad
{
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(dragMap:)];
panGesture.delegate = self;
[mapView addGestureRecognizer:panGesture];
}
-(void)dragMap:(UIPanGestureRecognizer*) gestureRecognizer
{
if(gestureRecognizer.state == UIGestureRecognizerStateBegan)
{
NSLog(#"The mapView Dragged");
}
}
I understand the problem.
Zoom or drag both the cases call regionWillChangeAnimated and regionDidChangeAnimated you want to differentiate between zoom and drag.
In MapViewControllerDelegate
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
// check mapView.centerCoordinate
// if mapView.centerCoordinate is equal previousCenterCoordinate {
// ZOOM
// } else {
//pinch gesture
//}
}
Update:
I thought my previous example will work. But it did not. This is my second attempt.
Add a method getZoomLevel
#define MERCATOR_OFFSET 268435456
#define MERCATOR_RADIUS 85445659.44705395
- (double) getZoomLevel
{
return 20.00 - log2(self.region.span.longitudeDelta * MERCATOR_RADIUS * M_PI / (180.0 * self.bounds.size.width));
}
In this method, self is mapView. I have a category of MKMapView so it is self in my case.
In MapViewControllerDelegate
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
// zoomLevel = [mapView getZoomLevel]; // or [self getZoomLevel] in your case
// if zoomLevel isEqual previousZoomLevel {
// did drag
// } else {
// did zoom
// previousZoomLevel = zoomLevel
//}
}

iOS: How to know zoom level of GMSMapView

Hello I want to get current zoom level of Google Map view, like in a condition to check.
For example,
if(mapView.zoom==18.0)
{
//code goes here..
}
How to get that ?
It's pretty easy. GMSMapView has a camera (GMSCameraPosition) property that has a zoom property.
CGFloat zoom = mapView.camera.zoom;
Note that zoom property is readonly.
You can use below code.
#define MERCATOR_RADIUS 85445659.44705395
#define MAX_GOOGLE_LEVELS 20
#interface MKMapView (ZoomLevel)
- (double)getZoomLevel;
#end
#implementation MKMapView (ZoomLevel)
- (double)getZoomLevel
{
CLLocationDegrees longitudeDelta = self.region.span.longitudeDelta;
CGFloat mapWidthInPixels = self.bounds.size.width;
double zoomScale = longitudeDelta * MERCATOR_RADIUS * M_PI / (180.0 * mapWidthInPixels);
double zoomer = MAX_GOOGLE_LEVELS - log2( zoomScale );
if ( zoomer < 0 ) zoomer = 0;
// zoomer = round(zoomer);
return zoomer;
}
#end
Also can use MKCoordinateSpan check document for more information.
typedef struct {
CLLocationDegrees latitudeDelta;
CLLocationDegrees longitudeDelta;
} MKCoordinateSpan;

Same MKOverlayView delegate called in one UIView but not another. What's missing?

My app tracks GPS movement as a MKPolyline routepath on a MKMapView as an MKOverlayRenderer in the HomeVC, saves the data, and displays it later, as a saved routepath a few VCs deeper, on DisplayVC. I can confirm that the data is identical to the original data on the second VC, and the proper routeBounds are used when the map is shown, but the OverlayRenderer is never called on the second VC. Why not? I'm thinking delegate problems, but I can't find anything wrong.
Both homeVC.h
#interface homeVC : UIViewController <CLLocationManagerDelegate, MKMapViewDelegate> {
and displayVC.h are the same, except for the name:
#interface displayVC : UIViewController <CLLocationManagerDelegate, MKMapViewDelegate> {
CLLocationManager *locationManager;
// the data representing the route points
MKPolyline* _routePath;
// the view we create for the line on the map
MKPolylineView* _routePathVw;
// the rect that bounds the loaded points
MKMapRect _routeBounds;
}
#property (nonatomic, weak) IBOutlet MKMapView *mapView;
#end
And both homeVC.m and displayVC.m are set up the same:
- (void)viewDidLoad {
[super viewDidLoad];
// Add the Map
[_mapView setDelegate:self];
_mapView.mapType = MKMapTypeStandard;
}
Lots of good-working code here. Then,
-(void) buildRoute {
CLLocationCoordinate2D thisCoord;
int i = [arrayLa count] - 1; // keep growing the array size
MKMapPoint *tmpArr = realloc(pointArr, sizeof(CLLocationCoordinate2D)*(arrayLa.count));
pointArr = tmpArr;
thisCoord.latitude = [[arrayLa objectAtIndex:i] floatValue];
thisCoord.longitude = [[arrayLo objectAtIndex:i] floatValue];
MKMapPoint point = MKMapPointForCoordinate(thisCoord);
pointArr[i] = point;
// Reset Map View Boundaries
if( point.x > ne_Pt.x - 500 ) ne_Pt.x = point.x + 1000;
if( point.y > ne_Pt.y - 500 ) ne_Pt.y = point.y + 1000;
if( point.x < sw_Pt.x + 500 ) sw_Pt.x = point.x - 1000;
if( point.y < sw_Pt.y + 500 ) sw_Pt.y = point.y - 1000;
// create the polyline based on the C-array of map Points
_routePath = [MKPolyline polylineWithPoints:pointArr count:arrayLa.count];
_routeBounds = MKMapRectMake(sw_Pt.x, sw_Pt.y, ne_Pt.x-sw_Pt.x, ne_Pt.y-sw_Pt.y);
// add the routePath overlay to the map, if it isn't empty
if (recState == REC && _routePath != nil) {
// zoom in on the route with the fresh bounding box, routeBounds
[self zoomInOnRoute];
[_mapView addOverlay:_routePath];
}
}
-(void) zoomInOnRoute {
[_mapView setVisibleMapRect:_routeBounds];
}
#pragma mark MKMapViewDelegate
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
if ([overlay isKindOfClass:[MKPolyline class]]) {
MKPolyline *route = overlay;
MKPolylineRenderer *routeRenderer = [[MKPolylineRenderer alloc] initWithPolyline:route];
routeRenderer.lineWidth = 3;
routeRenderer.strokeColor = [UIColor redColor];
return routeRenderer;
}
else return nil;
}
Can anyone help solve my problem?
Thanks!
It does look like a delegate issue. Have you tried putting a breakpoint on the addOverLay call just in case the 'if' is skipping it?
I do something similar and all works fine using MKOverlay and MKOverlayRender (based on the apple Breadcrumbs sample app but updated). The app displays a route that the user can save to CoreData. They can select from a table of saved routes and the route is rendered using MKOverlayRenderer.
Set the delegate
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.mapView setDelegate:self];
}
Create a MKOverlay and add to mapView
- (void)createRoute2
{
// Some CoreData stuff. Iterate through map points and create an overlay.
// Order by date ascending so we draw in sequential order
NSSortDescriptor *timeStampDescriptor = [[NSSortDescriptor alloc] initWithKey:#"pointDate" ascending:YES];
NSArray *sortDescriptors = #[timeStampDescriptor];
NSArray *routePts = [[self.selectedRoute mapDetail] sortedArrayUsingDescriptors:sortDescriptors];
// A long is a bit excessive just use an int is fine ( BUT might be a huge number of route points)
long nbrPts = routePts.count;
if (nbrPts < 2){
return;
}
CLLocationCoordinate2D mapPointLoc;
MKMapRect updateRect; // The map area
// Init the route
// FtfmapDetail is a managed object holding lat long (and other stuff)
FtfMapDetail *currentPt = (FtfMapDetail *)[routePts objectAtIndex:0];
mapPointLoc = CLLocationCoordinate2DMake([currentPt.latitude floatValue], [currentPt.longitude floatValue]);
// self.route is a subclassed MapOverlay
if (!self.route)
{
// BGSMapOverlay is a subclassed MapOverlay
self.route = [[BGSMapOverlay alloc] initWithCenterCoordinate:mapPointLoc];
[self.mapView addOverlay:self.route];
}
// Add subsequent points. Kick off the for loop at int position 1 not 0
for (int i=1; i <nbrPts; i++){
currentPt = (FtfMapDetail *)[routePts objectAtIndex:i];
mapPointLoc = CLLocationCoordinate2DMake([currentPt.latitude floatValue], [currentPt.longitude floatValue]);
// AddCoordinate is a method in MKOverlay subclass that returns a bounding MKMaprect for all points in MkOverlay
updateRect = [self.route addCoordinate:mapPointLoc];
}
MKCoordinateRegion region = MKCoordinateRegionForMapRect(self.route.boundingMapRectCompleteRoute);
[self.mapView setRegion:region animated:YES];
}
And make sure you add the delegate method
#pragma mark - MKMapView delegate
// self.routeViewRenderer is a sub-classed MKOverlayRendered (based on the Breadcrumbs app from apple CrumbPathView subclassed MKOverlayView)
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{
if (!self.routeViewRenderer)
{
_routeViewRenderer = [[BGSMKOverlayRender alloc] initWithOverlay:overlay];
}
return self.routeViewRenderer;
}
Or it could be that you are not sending any coordinates to the MkPolyLine. In the following snippet if I uncomment the "NSArray *routeCoordinates = [[NSArray alloc]init];" to send a Nil array to the MKPolyLine then the code will run but the delegate doesn't get called. If routeCoordinates contains points then delegate is called and route displayed.
-(void)buildRouteOverlays
{
for (int i=0; i< _routeHeaders.count;i++)
{
_selectedRoute = (FtfMaps*) [_routeHeaders objectAtIndex:i];
NSLog(#"DEBUG route date : %#", _selectedRoute.dateMap);
NSArray *routeCoordinates = [self arrayRoutePointCoordinates];
// if a nil array is produce then MapOverlayRenerder is not called - nothing to render
// Test this by uncommenting:
// NSArray *routeCoordinates = [[NSArray alloc]init];
NSLog(#"DEBUG number of point in Route : %lu",(unsigned long)routeCoordinates.count);
// Just a quick test only process the first route
if (i==0){
MKPolyline *routePolyLine = [self polyLineFromArray:routeCoordinates];
[self.mapView addOverlay:routePolyLine];
}
}
}
-(MKPolyline*)polyLineFromArray:(NSArray*)routePoints
{
NSInteger pointsCount = routePoints.count;
CLLocationCoordinate2D pointsToUse[pointsCount];
for(int i = 0; i < pointsCount; i++) {
FtfMapDetail *mapPt = (FtfMapDetail *) [routePoints objectAtIndex:i];
pointsToUse[i] = CLLocationCoordinate2DMake([mapPt.latitude doubleValue], [mapPt.longitude doubleValue]);
}
MKPolyline *myPolyline = [MKPolyline polylineWithCoordinates:pointsToUse count:pointsCount];
return myPolyline;
}
#pragma mark MKMapViewDelegate
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
if ([overlay isKindOfClass:[MKPolyline class]]) {
MKPolyline *route = overlay;
MKPolylineRenderer *routeRenderer = [[MKPolylineRenderer alloc] initWithPolyline:route];
routeRenderer.lineWidth = 3;
routeRenderer.strokeColor = [UIColor redColor];
return routeRenderer;
}
else return nil;
}

Resources