1
votes

Error Screenshot

Map Screenshot

I would like to draw a line between two annotation pins based on address strings. The address labels are pre-filled with data from the user and can be any location in the united states. I already have an annotation on each address, I am just unsure of what to put for the coordinate array (lat, long) in order to draw a line between these two points. I have attached 2 screenshots to help clarify and show the errors I am receiving.

Here is how I am annotating each address:

     NSString *location = [(UILabel *)[[self view] viewWithTag:1]text];;
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:location
             completionHandler:^(NSArray* placemarks, NSError* error){
                 if (placemarks && placemarks.count > 0) {
                     CLPlacemark *topResult = [placemarks objectAtIndex:0];
                     MKPlacemark *placemark = [[MKPlacemark alloc] initWithPlacemark:topResult];

                     MKCoordinateRegion region = self.mapView.region;


                     [self.mapView setRegion:region animated:NO];
                     [self.mapView addAnnotation:placemark];
                 }
             }
 ];

NSString *location2 = [(UILabel *)[[self view] viewWithTag:6]text];;
CLGeocoder *geocoder2 = [[CLGeocoder alloc] init];
[geocoder2 geocodeAddressString:location2
             completionHandler:^(NSArray* placemarks, NSError* error){
                 if (placemarks && placemarks.count > 0) {
                     CLPlacemark *topResult = [placemarks objectAtIndex:0];
                     MKPlacemark *placemark = [[MKPlacemark alloc] initWithPlacemark:topResult];

                     MKCoordinateRegion region = self.mapView.region;

                     [self.mapView setRegion:region animated:NO];
                     [self.mapView addAnnotation:placemark];


                 }
             }
 ];

Here is the error where I do not know what to put for latitude and longitude in the coordinate array:

      CLLocationCoordinate2D coordinateArray[2];
coordinateArray[0] =  CLLocationCoordinate2DMake(lat1, lon1);<- NEED HELP HERE
coordinateArray[2] = CLLocationCoordinate2DMake(lat2, lon2);<- NEED HELP HERE


self.routeLine = [MKPolyline polylineWithCoordinates:coordinateArray count:2];
[self.mapView setVisibleMapRect:[self.routeLine boundingMapRect]]; //If you want the route to be visible

[self.mapView addOverlay:self.routeLine];
2

2 Answers

2
votes

You should just build an array of coordinates, perhaps populating it from the array of annotations that you're going to add to the map. For example:

NSArray <NSString*> *addressStrings = @[@"Los Angeles, CA", @"Chicago, IL"];
CLGeocoder *geocoder = [[CLGeocoder alloc] init];

NSMutableArray <MKPlacemark *> *annotations = [NSMutableArray array];

// first request

[geocoder geocodeAddressString:addressStrings[0] completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
    if (placemarks.count == 0) {
        NSLog(@"didn't annotation for %@", addressStrings[1]);
        return;
    }

    [annotations addObject:[[MKPlacemark alloc] initWithPlacemark:placemarks[0]]];

    // second request

    [geocoder geocodeAddressString:addressStrings[1] completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
        if (placemarks.count == 0) {
            NSLog(@"didn't annotation for %@", addressStrings[1]);
            return;
        }

        [annotations addObject:[[MKPlacemark alloc] initWithPlacemark:placemarks[0]]];

        // when both are done

        CLLocationCoordinate2D coordinates[2];
        coordinates[0] = annotations[0].coordinate;
        coordinates[1] = annotations[1].coordinate;
        MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coordinates count:2];
        [self.mapView addAnnotations:annotations];
        [self.mapView addOverlay:polyline];
        [self.mapView showAnnotations:annotations animated:true];
    }];
}];

This assumes, of course, that you set the delegate for your map view accordingly and implemented rendererForOverlay:

- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
    if ([overlay isKindOfClass:[MKPolyline class]]) {
        MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithPolyline:overlay];
        renderer.lineWidth = 4;
        renderer.strokeColor = [[UIColor cyanColor] colorWithAlphaComponent:0.75];
        return renderer;
    }
    return nil;
}

chicago to la

Also note that the API dictates that you shouldn't perform concurrent geocode requests, so I've put one in the completion handler of another.

0
votes

Just change the coordinate of source and destination.

#pragma mark - Show Route Direction

-(void)loadRoute
{
    MKPlacemark *source = [[MKPlacemark alloc]initWithCoordinate:CLLocationCoordinate2DMake(34.0207504,-118.69193) addressDictionary:[NSDictionary dictionaryWithObjectsAndKeys:@"",@"", nil] ];

    MKMapItem *srcMapItem = [[MKMapItem alloc]initWithPlacemark:source];
    [srcMapItem setName:@""];

    MKPlacemark *destination = [[MKPlacemark alloc]initWithCoordinate:CLLocationCoordinate2DMake(37.757815,-122.5076406) addressDictionary:[NSDictionary dictionaryWithObjectsAndKeys:@"",@"", nil] ];

    MKMapItem *distMapItem = [[MKMapItem alloc]initWithPlacemark:destination];
    [distMapItem setName:@""];

    MKDirectionsRequest *request = [[MKDirectionsRequest alloc]init];
    [request setSource:srcMapItem];
    [request setDestination:distMapItem];
    [request setTransportType:MKDirectionsTransportTypeAutomobile];

    MKDirections *direction = [[MKDirections alloc]initWithRequest:request];

    [direction calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {

        NSLog(@"response = %@",response);
        NSArray *arrRoutes = [response routes];
        [arrRoutes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

            MKRoute *rout = obj;

            MKPolyline *line = [rout polyline];
            [self.mapView addOverlay:line];
            NSLog(@"Rout Name : %@",rout.name);
            NSLog(@"Total Distance (in Meters) :%f",rout.distance);

            NSArray *steps = [rout steps];

            NSLog(@"Total Steps : %lu",(unsigned long)[steps count]);

            [steps enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
                NSLog(@"Rout Instruction : %@",[obj instructions]);

            }];
        }];
    }];

}

- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
{

    if ([overlay isKindOfClass:[MKPolyline class]]) {
        MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
        [renderer setStrokeColor:[UIColor blueColor]];
        [renderer setLineWidth:3.0];
        return renderer;
    }
    return nil;
}

output