1

I have been facing problem which is mkoverlay color. When I open the mapview, sometimes instead of drawing walking path, it colors with biking activity. I do not know how to fix the problem. Even though I have not done any biking activity but it draws biking activity with blue color. enter image description here

Here is the code implementation.

- (void)showLines {

    NSUserDefaults *def = [NSUserDefaults standardUserDefaults];

    NSArray* coordinate_array = [[NSArray alloc] init];
    int arrayCount = 0;
        // walking
    NSData *data =[def objectForKey:@"walking_coordinate"];
    NSMutableArray *walking_array = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    coordinate_array = [NSArray arrayWithArray:walking_array];
    arrayCount = (int)[walking_array count];
    color = 1;
    [self parseArray:coordinate_array withArrayCount:arrayCount];

        // driving
    data =[def objectForKey:@"driving_coordinate"];
    NSMutableArray *driving_array = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    coordinate_array = [NSArray arrayWithArray:driving_array];
    arrayCount = (int)[driving_array count];
    color = 2;
    [self parseArray:coordinate_array withArrayCount:arrayCount];

        // biking
    data =[def objectForKey:@"biking_coordinate"];
    NSMutableArray *biking_array = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    coordinate_array = [NSArray arrayWithArray:biking_array];
    arrayCount = (int)[biking_array count];
    color = 3;
    [self parseArray:coordinate_array withArrayCount:arrayCount];

}

- (void) parseArray:(NSArray *) coordinate_array withArrayCount:(int)arrayCount
{
    NSMutableArray *tempArray = [[NSMutableArray alloc] initWithCapacity:0];

    for (int i = 0; i < arrayCount; i++) {
        CoordinateModel *coord = [coordinate_array objectAtIndex:i];
        [tempArray addObject:coord];

        if ((int)coord.latitude == -1 || (int)coord.longitude == -1 || i == arrayCount-1) {
            // this is end of one segment
            [tempArray removeLastObject];
            CLLocationCoordinate2D *pointsCoordinate = (CLLocationCoordinate2D *)malloc(sizeof(CLLocationCoordinate2D) * [tempArray count]);

            for (int j = 0; j < [tempArray count]; j++) {
                CoordinateModel *point = [tempArray objectAtIndex:j];
                CLLocationCoordinate2D old_coordinate = CLLocationCoordinate2DMake(point.latitude, point.longitude);
                pointsCoordinate[j] = old_coordinate;
            //  NSLog(@"(%f, %f)", old_coordinate.latitude, old_coordinate.longitude);
            }
            if ([tempArray count] > 0) {
                int countTemp = (int)[tempArray count];
                MKPolyline *polyline = [MKPolyline polylineWithCoordinates:pointsCoordinate count:countTemp];
                [mapView addOverlay:polyline];
                [tempArray removeAllObjects];
            }
        }
    }

}

- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{
    if([overlay isKindOfClass:[MKPolyline class]])
    {
        MKPolylineView *lineView = [[MKPolylineView alloc] initWithPolyline:overlay];
        lineView.lineWidth = 8;

        if (color == 1) {
            // walking
            lineView.strokeColor = [UIColor greenColor];
            lineView.fillColor = [UIColor greenColor];
        }
        else if(color == 2) {
            // driving
            lineView.strokeColor = [UIColor redColor];
            lineView.fillColor = [UIColor redColor];
        }
        else if(color == 3) {
            // biking
            lineView.strokeColor = [UIColor blueColor];
            lineView.fillColor = [UIColor blueColor];
        }
        else {
            lineView.strokeColor = [UIColor blackColor];
            lineView.fillColor = [UIColor blackColor];
        }

        return lineView;
    }
    return nil;
}

2 Answers2

0

In the viewForOverlay delegate method, the overlay color is set using the external variable color which is set before calling parseArray for each type of overlay.

However, there is no guarantee when the delegate method will be called by the map view and it's possible for the delegate method to be called multiple times for the same overlay after you've already added all the overlays (eg. if you zoom/pan the map and the overlay comes back into view).

Since the last color value you set is 3 (for "biking"), any calls that the map view makes to the delegate method after the overlays are already added will end up drawing the overlay with the biking color.


To fix this, you need to be able to determine what color to draw the overlay inside the delegate method itself using some property of the overlay parameter (and not relying on some external variable).

The simplest way to do this is to use the MKPolyline's title property.
See this answer and this answer that explain the fact that MKPolyline has a title property.

So what you could do in your case is:

  1. Make color a parameter that you pass to your parseArray method.
  2. In the parseArray method, after creating polyline, set its title to the color:

    polyline.title = [NSString stringWithFormat:@"%d", color];
    
  3. In viewForOverlay, check the overlay's title property and set the color accordingly. See a specific example in different coloured polygon overlays (it shows it for polygon but the same can be done with polylines).

Community
  • 1
  • 1
  • Thank you so much Anna, for providing very detail answer as always. –  May 23 '14 at 03:23
  • I would be glad if you have time to help me out another question that I have recently posted http://stackoverflow.com/questions/23820252/cllocationmanager-coordinates –  May 23 '14 at 03:25
  • Anna, I would be happy if you could able to take a look the my question which related your expertise. http://stackoverflow.com/questions/23833758/gps-coordinate-accuracy –  May 23 '14 at 16:11
0

Here is the answer based on Anna answer to help whomever wants to see in code.

 - (void)showLines2 {


        NSUserDefaults *def = [NSUserDefaults standardUserDefaults];

        NSArray* coordinate_array = [[NSArray alloc] init];
        int arrayCount = 0;
            // walking
        NSData *data =[def objectForKey:@"walking_coordinate"];
        NSMutableArray *walking_array = [NSKeyedUnarchiver unarchiveObjectWithData:data];
        coordinate_array = [NSArray arrayWithArray:walking_array];
        arrayCount = (int)[walking_array count];
        color = 1;
        [self parseArray:coordinate_array withArrayCount:arrayCount withColor:color];

            // driving
        data =[def objectForKey:@"driving_coordinate"];
        NSMutableArray *driving_array = [NSKeyedUnarchiver unarchiveObjectWithData:data];
        coordinate_array = [NSArray arrayWithArray:driving_array];
        arrayCount = (int)[driving_array count];
        color = 2;
        [self parseArray:coordinate_array withArrayCount:arrayCount withColor:color];

            // biking
        data =[def objectForKey:@"biking_coordinate"];
        NSMutableArray *biking_array = [NSKeyedUnarchiver unarchiveObjectWithData:data];
        coordinate_array = [NSArray arrayWithArray:biking_array];
        arrayCount = (int)[biking_array count];
        color = 3;
        [self parseArray:coordinate_array withArrayCount:arrayCount withColor:color];

    }


- (void) parseArray:(NSArray *) coordinate_array withArrayCount:(int)arrayCount withColor:(int)polyColor
{
    NSMutableArray *tempArray = [[NSMutableArray alloc] initWithCapacity:0];

    for (int i = 0; i < arrayCount; i++) {
        CoordinateModel *coord = [coordinate_array objectAtIndex:i];
        [tempArray addObject:coord];

        if ((int)coord.latitude == -1 || (int)coord.longitude == -1 || i == arrayCount-1) {
            // this is end of one segment
            [tempArray removeLastObject];
            CLLocationCoordinate2D *pointsCoordinate = (CLLocationCoordinate2D *)malloc(sizeof(CLLocationCoordinate2D) * [tempArray count]);

            for (int j = 0; j < [tempArray count]; j++) {
                CoordinateModel *point = [tempArray objectAtIndex:j];
                CLLocationCoordinate2D old_coordinate = CLLocationCoordinate2DMake(point.latitude, point.longitude);
                pointsCoordinate[j] = old_coordinate;
            //  NSLog(@"(%f, %f)", old_coordinate.latitude, old_coordinate.longitude);
            }
            if ([tempArray count] > 0) {
                int countTemp = (int)[tempArray count];
                MKPolyline *polyline = [MKPolyline polylineWithCoordinates:pointsCoordinate count:countTemp];
                polyline.title = [NSString stringWithFormat:@"%d", color];
                [mapView addOverlay:polyline];
                [tempArray removeAllObjects];
            }
        }
    }

}

    - (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
    {
        if([overlay isKindOfClass:[MKPolyline class]])
        {
            MKPolylineView *lineView = [[MKPolylineView alloc] initWithPolyline:overlay];
            lineView.lineWidth = 8;

    //      ActivityType currentActivityType = [DataManager sharedInstance].activityType;
            if ([overlay.title isEqualToString:@"1"]) {
                // walking
                lineView.strokeColor = [UIColor greenColor];
                lineView.fillColor = [UIColor greenColor];
            }
            else if([overlay.title isEqualToString:@"2"]) {
                // driving
                lineView.strokeColor = [UIColor redColor];
                lineView.fillColor = [UIColor redColor];
            }
            else if([overlay.title isEqualToString:@"3"]) {
                // biking
                lineView.strokeColor = [UIColor blueColor];
                lineView.fillColor = [UIColor blueColor];
            }
            else {
                lineView.strokeColor = [UIColor blackColor];
                lineView.fillColor = [UIColor blackColor];
            }

            return lineView;
        }
        return nil;
    }