3

I want the user to be able to create polygons after placing some (unknown number) MKpointAnnotations in the map.I have put a gesture recognizer that gets activated once the user taps a button, and so annotations are placed.But how to use these as corners for a MKPolygon? Below the code for saving the corners of the polygon.This after some mods I did to it.Now the app crashes and the crash reporter says index out of range.The corners are MKPointAnnotation-s created via a GestureRecognizer.

-(IBAction)addCorner:(id)sender
{
NSMutableArray *addCorners = [[NSMutableArray alloc] init];
[addCorners addObject:pointAnnotation];
ptsArray = addCorners;
}

-(IBAction)addPolygonOverlay:(id)sender
{
int cornersNumber = sizeof(ptsArray);
MKMapPoint points[cornersNumber];

for (int i=0; i<cornersNumber; i++) {
    points[i] = MKMapPointForCoordinate([[ptsArray objectAtIndex:i] coordinate]);
}

MKPolygon *polygon = [MKPolygon polygonWithPoints:points count:cornersNumber];
[mapview addOverlay:polygon];

}
  • How are you storing the list of corners (annotations) of the polygon? What have you tried? –  Oct 31 '11 at 16:39

1 Answers1

1

First problem is the addCorner method. Instead of adding each corner to the ptsArray variable, it creates a new array with just the last corner and sets theptsArray equal to that so it only has the one, last corner.

Change the addCorner method like this:

-(IBAction)addCorner:(id)sender
{
    if (ptsArray == nil)
    {
        self.ptsArray = [NSMutableArray array];
    }

    [ptsArray addObject:pointAnnotation];
}

Also make sure ptsArray is declared and synthesized properly:

//in the .h file...
@property (nonatomic, retain) NSMutableArray *ptsArray;
//in the .m file...
@synthesize ptsArray;

(By the way, why not add the corner to ptsArray right where the pointAnnotation is created instead of in a separate user action?)


Second problem is in the addPolygonOverlay method. You have to use the NSArray count property to get the number of items in the array. The sizeof function returns the number of bytes of physical memory the passed variable uses. For ptsArray which is a pointer, it will return 4. If the ptsArray has less than 4 items, you will get the "index out of range" exception.

So change

int cornersNumber = sizeof(ptsArray);

to

int cornersNumber = ptsArray.count;


Another important thing to note is that the polygon sides will be drawn in the order the points are in the array. If the user does not add corners in a clockwise or counter-clockwise order, the polygon will look strange. You could re-create the polygon overlay immediately after a user adds/removes an annotation so they get immediate feedback on how it will look.

  • I understand what I was doing wrong.I tried what you said and it worked like a charm!By the way, I think I will do what you said about adding the corner to 'ptsArray' right where the 'pointAnnotation' is created.How silly I was using the 'sizeof' function,I totally forgot the 'count' property'.Thanks for all your help, really precious! –  Nov 12 '11 at 13:58
  • 1
    Can I ask an opinion? I am creating two overlays and using gesture recognizers,,a LongPressure(1sec)_circle) and Tap(poly).The problem is that after I have tapped both buttons that activate these gesture recognizers and the creation of the overlays(first I have done a circle and then a polygon), when i want to create a second circle, I get two pins, one "as a tap" and one after a second...I think to try creating a global gesture recognizer initiaded in the 'viewdidload' method and then "customize" mkmapponits usage locally within button tap-action methods i mentioned before.What do you think? –  Nov 12 '11 at 14:08
  • 1
    You probably want to ask a new question for that but a simple solution is to keep only one gesture recognizer enabled at a time. When user taps button to create circle, enable long-press-gr and disable tap-gr. Do the reverse when user taps button to create polygon. Displaying a label somewhere showing which gr is currently active would be helpful to the user. –  Nov 12 '11 at 15:24