MKMapView freezes on User Interaction - ios

I have an application where I show a small map with one annotation, the map is in a objectDetailScreen that I created, this screen is updated whenever a new object is set, also showing a new map. The map as a annotation for the object.
Whenever I try to move the view, tap the annotations pin or zoom, the map freezes for a while and I have no clue why it does that. The app is iPad only (iPad 2, iOS 4.3.5). Here is the code that sets the map:
- (void) setObject:(AchmeaObject *)_object
{
if(kaart != nil)
{
[kaart removeFromSuperview];
kaart = nil;
}
kaart = [[MKMapView alloc] initWithFrame:CGRectMake(340, 380, 400,300)];
[kaart setDelegate: self];
[kaart setUserInteractionEnabled:YES];
CLLocationCoordinate2D coordinate;
coordinate.latitude = [_object.latitude doubleValue];
coordinate.longitude = [_object.longitude doubleValue];
double miles = 2;
double scalingFactor = ABS( cos(2 * M_PI * coordinate.latitude /360.0) );
MKCoordinateSpan span;
span.latitudeDelta = miles/69.0;
span.longitudeDelta = miles/(scalingFactor*69.0);
MKCoordinateRegion region;
region.span = span;
region.center = coordinate;
[kaart setRegion: region animated:YES];
ObjectAnnotation *sa = [[ObjectAnnotation alloc] initWithName: _object.plaats Address: _object.adres Coordinate:coordinate];
NSArray *anotations = [NSArray arrayWithObject: sa];
[kaart addAnnotations:anotations];
[self.view addSubview:kaart];
}
I have no idea why it happens, but when it first shows it takes a few seconds to respond to any user interaction, and after every interaction it needs at least a few more seconds, until after a few times freezing completely.
ObjectAnnotation.m
#import "ObjectAnnotation.h"
#implementation ObjectAnnotation
#synthesize coordinate = _coordinate;
- (id) initWithName: (NSString *) _name Address: (NSString *) _address Coordinate: (CLLocationCoordinate2D) _coord{
self = [super init];
name = [_name retain];
address = [_address retain];
_coordinate = _coord;
return self;
}
- (NSString *)title {
return name;
}
- (NSString *)subtitle {
return address;
}
- (void)dealloc
{
[name release];
name = nil;
[address release];
address = nil;
[super dealloc];
}
#end

I suspect this is related to re-adding new map views. Add a map view in the xib or very early in the view controller's life cycle and keep it hidden, and then show it and update its position (with setRegion:animated:). Creating a new map view each time is both expensive and unnecessary; if you're doing it because you want to get rid of some state (annotations, the map's region), learn how to reset that state in the existing map view instead.
It could also be related to your ObjectAnnotation, to which you do not provide the source code.

I suffered the same problem. After profiling, I find out tint property could be causing the map refresh delay. So I set default tint at storyboard and problem disappeared.

Related

Within a UICollectionViewCell, setRegion has no effect for a MKMapView

I have set up a simple MKMapView (it is intended just to display a location on the map and nothing more) within one cell of a section of a CollectionView and am unable to set its region using setRegion. The MKMapViewDelegate is correctly set to the UICollectionViewCell as shown by breakpoints being hit within all the delegate methods.
I first tried to set the region in the View Controller's cellForItemAtIndexPath but I'm guessing this is too early, i.e. before the map is loaded so nothing happens and it loads a default location in the middle of the ocean.
I have tried passing the CLCoordinateLocation2D from the view controller to a CLCoordinateLocation2D in the cell during cellForItemAtIndexPath to set the region within the cell but where is the appropriate place to set the region? In a ViewController it should be done in ViewDidAppear rather than ViewDidLoad or ViewWillAppear so that the map is loaded but I cannot find an equivalent event for a collectionviewcell. awakeFromNib is clearly too soon. I have tried using various mapView delegates such as:
- (void)mapView:(MKMapView *)mapView1
regionWillChangeAnimated:(BOOL)animated
{
MKCoordinateSpan span = {.latitudeDelta = 0.0025, .longitudeDelta = 0.0025};
MKCoordinateRegion adjustedRegion = [mapView1 regionThatFits:MKCoordinateRegionMakeWithDistance(coords, 200, 200)];
[mapView1 setRegion:adjustedRegion animated:YES];
}
which runs but again does not change the region. I have tried
- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView and
- (void)mapViewWillStartRenderingMap:(MKMapView *)mapView
which seemed the best bets but a breakpoint before and after the setRegion line shows the region is never updated to the region I'm setting it to. The events all should be at a time that the map is fully loaded so why does setRegion simply have no effect??
Cell h file:
#interface BasicsCollectionViewCell : UICollectionViewCell
#property (strong, nonatomic) IBOutlet MKMapView *mapView;
#property (nonatomic) CLLocationCoordinate2D coords;
#end
Cell m file:
#interface BasicsCollectionViewCell() <MKMapViewDelegate>
#end
#implementation BasicsCollectionViewCell
#synthesize mapView;
#synthesize coords;
- (void)mapView:(MKMapView *)mapView1
regionWillChangeAnimated:(BOOL)animated
{
MKCoordinateSpan span = {.latitudeDelta = 0.0025, .longitudeDelta = 0.0025};
MKCoordinateRegion adjustedRegion = [mapView1 regionThatFits:MKCoordinateRegionMakeWithDistance(coords, 200, 200)];
[mapView1 setRegion:adjustedRegion animated:YES];
}
And the relevant part of cellForItemAtIndexPath:
cell0 = (BasicsCollectionViewCell*)[collectionView dequeueReusableCellWithReuseIdentifier:#"BasicsCell" forIndexPath:indexPath];
CLLocationCoordinate2D coord = {.latitude = self.latitude, .longitude = self.longitude};
[cell0 setCoords:coord];
cell0.mapView.delegate = cell0;
MKCoordinateSpan span = {.latitudeDelta = 0.0025, .longitudeDelta = 0.0025};
MKCoordinateRegion adjustedRegion = [cell0.mapView regionThatFits:MKCoordinateRegionMakeWithDistance(coord, 200, 200)];
[cell0.mapView setRegion:adjustedRegion animated:YES];
return cell0;
EDIT:
If I put breakpoints in the following code before and after the setRegion line at the asterixed points...
- (void)mapViewWillStartRenderingMap:(MKMapView *)mapView
{
MKCoordinateSpan span = {.latitudeDelta = 0.0025, .longitudeDelta = 0.0025};
MKCoordinateRegion adjustedRegion = [mapView regionThatFits:MKCoordinateRegionMakeWithDistance(coords, 200, 200)];
*****[mapView setRegion:adjustedRegion animated:YES];
*****}
then the debugger gives the following at the first breakpoint:
po self.mapView.region
{
(latitude = -41.508575000000008, longitude = 174.19921900000011)
(latitudeDelta = 13.733789001832008, longitudeDelta = 59.305518116231042)
}
And the same at the breakpoint immediately after:
po self.mapView.region
{
(latitude = -41.508575000000008, longitude = 174.19921900000011)
(latitudeDelta = 13.733789001832008, longitudeDelta = 59.305518116231042)
}
While at both breakpoints, the following is the (correct) value of adjustedRegion:
po adjustedRegion
{
(latitude = -0.13506928037132482, longitude = 51.518398284912109)
(latitudeDelta = 0.0018087389042361623, longitudeDelta = 0.0058458603824931288)
}
So it is simply that either setRegion is being ignored for some reason or it’s overridden by something else. Any ideas which?
I have faced similar one, where map region was not changed. So I manually called mapView delegate method
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated;
in - (void) viewDidAppear:(BOOL)animated of view controller.
- (void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// Manually called delegate method to forcefully set region.
[self mapView:self.mapView regionDidChangeAnimated:YES];
}
In your case call this method right after when you set map region. From your above code for example in cellForItemAtIndexPath method. For example:
cell0 = (BasicsCollectionViewCell*)[collectionView dequeueReusableCellWithReuseIdentifier:#"BasicsCell" forIndexPath:indexPath];
CLLocationCoordinate2D coord = {.latitude = self.latitude, .longitude = self.longitude};
[cell0 setCoords:coord];
cell0.mapView.delegate = cell0;
MKCoordinateSpan span = {.latitudeDelta = 0.0025, .longitudeDelta = 0.0025};
MKCoordinateRegion adjustedRegion = [cell0.mapView regionThatFits:MKCoordinateRegionMakeWithDistance(coord, 200, 200)];
[cell0.mapView setRegion:adjustedRegion animated:YES];
[cell0.mapView setRegion:adjustedRegion animated:YES];
// Force call of delegate method
[self mapView:cell0.mapView regionDidChangeAnimated:YES];
return cell0;
Note:
Don't forgot to override regionDidChangeAnimated method in view controller.
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
}

MKPinAnnotationView color is not working

I am trying to show some pins from an array, it shows them all but they are red, and not green as i ask them to be.
Why is that ?
//run on array to get all locations
for(int k=0;k<[array count];k=k+2)
{
float targetlat=[[array objectAtIndex:k] floatValue];
float targetlongi=[[array objectAtIndex:k+1] floatValue];
CLLocationCoordinate2D location = CLLocationCoordinate2DMake(targetlat,targetlongi);
NSString *partyTitle = #"title";
MKPinAnnotationView *partyPin = [self returnPointView:location andTitle:partyTitle andColor:MKPinAnnotationColorGreen];
[self.mapView addAnnotation:partyPin.annotation];
}
//function callback is working but its red, and it takes so much time to load
-(MKPinAnnotationView*) returnPointView: (CLLocationCoordinate2D) location andTitle: (NSString*) title andColor: (int) color
{
MKCoordinateRegion region = self.mapView.region;
region.center = location;
region.span.longitudeDelta /= 5.0;
region.span.latitudeDelta /= 5.0;
[self.mapView setRegion:region];
MKPointAnnotation *resultPin = [[MKPointAnnotation alloc] init];
MKPinAnnotationView *result = [[MKPinAnnotationView alloc] initWithAnnotation:resultPin reuseIdentifier:Nil];
[resultPin setCoordinate:location];
resultPin.title = title;
result.pinColor = color;
return result;
}
Regarding the main issue that the pins are red instead of green:
The code creates an MKPinAnnotationView but this view is never given to the map view.
To make the map view use annotation views that you create, you must implement the viewForAnnotation delegate method and return them from there.
Otherwise, the map view has no knowledge of annotation views that you create.
If you don't implement viewForAnnotation, the map view creates a default red pin view.
Regarding the second issue that "it takes so much time to load":
The most likely reason for this is that you are calling setRegion each time you add an annotation.
If you are adding, say, 500 annotations, the map view is setting the region 500 times.
Please note that it is not necessary to call setRegion simply to add an annotation (regardless of the currently-visible region). The annotation's coordinate does not have to be "visible" to add an annotation there.
What you want to do inside the for loop is simply construct a region that includes all the annotations and then call setRegion (or setVisibleRect) once and after all the annotations are added (after the for loop). Constructing an MKMapRect and calling setVisibleMapRect is easier than constructing an MKCoordinateRegion in order to call setRegion.
In iOS 7, this is even simpler: Just call showAnnotations (no manual construction necessary).
Example:
//Initialize the MKMapRect (region) we want to show to null...
MKMapRect showMapRect = MKMapRectNull;
for(int k=0;k<[array count];k=k+2)
{
float targetlat=[[array objectAtIndex:k] floatValue];
float targetlongi=[[array objectAtIndex:k+1] floatValue];
CLLocationCoordinate2D location = CLLocationCoordinate2DMake(targetlat,targetlongi);
NSString *partyTitle = #"title";
//Here, don't create the annotation view.
//Just create the annotation...
MKPointAnnotation *resultPin = [[MKPointAnnotation alloc] init];
[resultPin setCoordinate:location];
resultPin.title = partyTitle;
[self.mapView addAnnotation:resultPin];
//Add this annotation's coordinate
//to the MKMapRect we want to show...
MKMapPoint annMapPoint = MKMapPointForCoordinate(location);
MKMapRect annMapRect = MKMapRectMake(annMapPoint.x, annMapPoint.y, 0, 0);
showMapRect = MKMapRectUnion(showMapRect, annMapRect);
}
mapView.visibleMapRect = showMapRect;
//In iOS 7, instead of constructing MKMapRect manually,
//we could just call showAnnotations...
//[mapView showAnnotations:mapView.annotations animated:YES];
//Implement the viewForAnnotation delegate method...
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
//if annotation is the user location,
//return nil so map view shows default view for it (blue dot)...
if ([annotation isKindOfClass:[MKUserLocation class]])
{
return nil;
}
static NSString *reuseId = #"pin";
MKPinAnnotationView *pav = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:reuseId];
if (pav == nil)
{
pav = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId];
pav.canShowCallout = YES;
pav.animatesDrop = YES;
pav.pinColor = MKPinAnnotationColorGreen;
}
else
{
pav.annotation = annotation;
}
return pav;
}

MKPolyline not showing on MKMapView

Here's the code. Its pretty straight forward. I'm making a path for someone who is walking.
So, here's the code for my ViewController.m file :
#import "ViewController.h"
#interface ViewController ()
#property BOOL firstTime;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.mapView setDelegate:self];
[self.mapView setShowsUserLocation:YES];
[self.mapView setMapType:MKMapTypeHybrid];
[self setLocationManager:[[CLLocationManager alloc] init]];
[self.locationManager setDelegate:self];
[self.locationManager setDistanceFilter:kCLDistanceFilterNone];
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.locationManager startUpdatingLocation];
self.index = 0;
self.firstTime = YES;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
if(self.firstTime)
{
CLLocation *startingLocation = [locations objectAtIndex:0];
self.startingPointCooridinates = startingLocation.coordinate;
self.index++;
MKPointAnnotation *startingPointAnnotation = [[MKPointAnnotation alloc] init];
startingPointAnnotation.title = #"Starting Point";
startingPointAnnotation.coordinate = startingLocation.coordinate;
[self.mapView addAnnotation:startingPointAnnotation];
self.firstTime = false;
}
[self.locations addObject:[locations objectAtIndex:0]];
CLLocationCoordinate2D coordinates[[self.locations count]];
for(int i = 0; i < self.locations.count; i++)
{
CLLocation *currentLocation = [locations objectAtIndex:i];
coordinates[i] = currentLocation.coordinate;
}
MKPolyline *pathPolyline = [MKPolyline polylineWithCoordinates:coordinates count:self.locations.count];
[self.mapView addOverlay:pathPolyline];
}
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
{
if([overlay isKindOfClass:[MKPolyline class]])
{
MKPolylineRenderer *polylineRenderer = [[MKPolylineRenderer alloc] initWithPolyline:overlay];
polylineRenderer.fillColor = [[UIColor redColor] colorWithAlphaComponent:0.2];
polylineRenderer.strokeColor = [[UIColor redColor] colorWithAlphaComponent:0.7];
polylineRenderer.lineWidth = 2.0;
return polylineRenderer;
}
else
{
return nil;
}
}
Now, only the annotation is showing and there isn't any MKPolyline showing up. What am I doing wrong ? Thanks.
As mentioned in the comments, your locations array is never allocated and initialized so it's nil and calls to it (like addObject) do nothing and so the polyline never gets any coordinates added to it (and so it doesn't show).
In viewDidLoad, before starting the CLLocationManager, alloc and init the array:
self.locations = [NSMutableArray array];
Another issue you will encounter is with this line in didUpdateLocations in the for loop:
CLLocation *currentLocation = [locations objectAtIndex:i];
Here, locations (without the self.) refers to the delegate method's local parameter variable and not your locations class-instance-level property variable. The compiler must be warning you about this with a message like "Local declaration of 'locations' hides instance variable".
In this case, the warning is critical. What you really mean to do here is reference the locations property variable where you are storing the user's complete trail of coordinates and not the local variable which only has the last x un-reported locations (usually only 1 object).
So that line should be changed to:
CLLocation *currentLocation = [self.locations objectAtIndex:i];
It would be better if you just used a different name than locations to avoid these problems.
As also mentioned in the comments, since you are adding an overlay with the user's complete trail of motion every time the user moves, you need to remove the previous overlay first. Otherwise, you will needlessly be adding multiple overlays to the map since the last overlay covers the entire motion. The previous overlays are not obviously visible since they have the same coordinates, the same color, and the same line width. So before calling addOverlay, the simplest thing to do is call removeOverlays with map's current list of overlays:
//remove any previous overlays first...
[self.mapView removeOverlays:mapView.overlays];
//now add overlay with the updated trail...
[self.mapView addOverlay:pathPolyline];
A minor point not affecting the display is that setting fillColor for a polyline has no effect. You only need to set strokeColor which the code is doing. You can remove the call to set fillColor.
Finally, you may be interested in seeing Apple's Breadcrumb sample app. Their version uses a custom overlay which can be dynamically updated without having to remove and add overlays every time there's a change or addition.

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

add Marker on the Map using Mappy SDK IOS

i'm developing and iphone app and i'm working with Mappy SDK IOS.
i arrived to display the map and show my current location. but i have a problem with adding some markers on my map.
i have an NSArray that contains some objects with longitude and latitude properties.
my code to display the markers is :
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
//initialisation mot de passe + user
[MPInit initialisation:MAPPY_API_KEY];
[RMMapView class];
//show user location
self.mapView.showsUserLocation = NO;
self.mapView.showPoi = YES;
//set delegate
self.mapView.delegate = self;
MPMarkerManager *markerManager = [self.mapView markerManager];
MPMarkerCategory * category = [markerManager getCategory:#"storeLocations"];
//remove old elements
[category.dataSource removeAllElements];
//add markers on map
for(int i=0; i<self.arrayStores.count; i++) {
NSLog(#"add store %d on the map", i);
NSDictionary* currentStore = [self.arrayStores objectAtIndex:i];
float latitude = [[currentStore objectForKey:#"latitude"] floatValue];
float longitude = [[currentStore objectForKey:#"longitude"] floatValue];
CLLocationCoordinate2D locationStore = CLLocationCoordinate2DMake(latitude, longitude);
//create a new POI object with location
MPPoi * poi = [[MPPoi alloc] initWithUId:[currentStore objectForKey:#"title"] withLocation:locationStore];
[category.dataSource addElement:poi];
self.mapView.centerCoordinate = locationStore;
[poi release];
}
//category settings
category.markerColor = [UIColor greenColor];
//[category setOptimalZoom:YES];//set the zoom to be optimal : show all poi in the category
[category setHideLabelOnTheFirstShow:NO];
[category setAnimateAtFirstShow:YES];
}
and here is the log displayed on the console:
2012-06-14 17:01:18.359 Koutoubia[609:607] MappyKit version:1.40
2012-06-14 17:01:18.672 Koutoubia[609:607] add store 0 on the map
i'm i doing something wrong ?? because markers aren't displayed
the doc for adding markers on the documentation is :
//add a marker on map
MPMarkerManager *markerManager = [viewController.mapView markerManager];
MPMarkerCategory * category = [markerManager getCategory:HMP_LOC_CATEGORY];
//remove old elements
[category.dataSource removeAllElements];
//create a new POI object with location
MPPoi * poi = [[MPPoi alloc] initWithUId:locationData.address withLocation:findLocation];
[category.dataSource addElement:poi];
[poi release];
the link of the documentation is here
any ideas ?? thanks in advance
I've founded the solution ,
the problem is that i've forgot to initialize the MPMarkerCategory and add it to the markerManager on the viewDidLoad method :
//Marker initialization
MPMarkerManager *markerManager = [self.mapView markerManager];
//add a new category with green default color
[markerManager addCategory:STORE_LOC_CATEGORY withColor:[UIColor greenColor]];

Resources