This is the one I found here that worked for me:
(EDIT: I have updated the solution using @Micah's suggestion to increase the pointRect by 0.1 to ensure the rect doesn't end up being infinitesimally small!)
MKMapRect zoomRect = MKMapRectNull;
for (id <MKAnnotation> annotation in mapView.annotations)
{
MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
zoomRect = MKMapRectUnion(zoomRect, pointRect);
}
[mapView setVisibleMapRect:zoomRect animated:YES];
You could also update this to include the userLocation pin by replacing the first line with:
MKMapPoint annotationPoint = MKMapPointForCoordinate(mapView.userLocation.coordinate);
MKMapRect zoomRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
The routeLine
and routeLineView
variables can only point to one overlay and overlay view at a time so you would theoretically need an array of such variables.
However, based on the code shown, you don't need to keep references to these in the first place.
I suggest removing the routeLine
and routeLineView
variables.
Then you just create an overlay object locally and in viewForOverlay
return a view for the requested overlay
parameter.
In the loadRoute
method, you can loop through the routesArray
and for each route, create a local overlay object, and call addOverlay
on it.
There's also an easier way to construct a map rect that bounds all the routes so you can set the map's region to show them all.
Example:
-(void) loadRoute
{
_routeRect = MKMapRectNull;
for (int raIndex = 0; raIndex < routesArray.count; raIndex++)
{
//So we grab an array that holds all the locations of one route.
NSArray *locations = [[NSArray alloc] initWithArray:
[routesArray objectAtIndex:raIndex]];
//note we are getting object at raIndex (not 0) above
//...no change to existing code here...
//self.routeLine = [MKPolyline polylineWithPoints:pointArr count:[locations count]];
//replace above line with this...
MKPolyline *pl = [MKPolyline polylineWithPoints:pointArr count:[locations count]];
[mapView addOverlay:pl];
//Zoom in to fit route on screen
//_routeRect = MKMapRectMake(southWestPoint.x, southWestPoint.y, northEastPoint.x - southWestPoint.x, northEastPoint.y - southWestPoint.y);
//replace above line with this to create a rect around ALL routes...
if (MKMapRectIsNull(_routeRect))
_routeRect = pl.boundingMapRect;
else
_routeRect = MKMapRectUnion(_routeRect, pl.boundingMapRect);
// clear the memory allocated earlier for the points
free(pointArr);
}
}
In viewDidLoad
, just call loadRoute
and don't call addOverlay
.
The viewForOverlay
method becomes much simpler:
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
MKPolylineView *pv = [[MKPolylineView alloc] initWithPolyline:overlay];
pv.fillColor = [UIColor redColor];
pv.strokeColor = [UIColor redColor];
pv.lineWidth = 3;
return pv;
}
By the way, in loadRoute
, this line:
MKMapPoint* pointArr = malloc(sizeof(CLLocationCoordinate2D) *[locations count]);
should be:
MKMapPoint* pointArr = malloc(sizeof(MKMapPoint) *[locations count]);
It should use the size of MKMapPoint
(not CLLocationCoordinate2D
).
They are not the same thing (even though the structs happen to be the same byte size).
Best Answer