1

当我初始化地图时,它会同时显示我的位置和目的地(从字符串转发地理编码),但不会在它们之间绘制方向。

这是我的代码:

#import "EventDetailMapViewController.h"

@interface EventDetailMapViewController ()
@property (nonatomic,strong) MKMapItem *destination;
@end

@implementation EventDetailMapViewController

CLPlacemark *thePlacemark;
MKRoute *routeDetails;


- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    _mapView.showsUserLocation = YES;
    self.navigationController.toolbarHidden = NO;

    _mapView.delegate = self;
    [self getRoute];

}


- (void)addAnnotation:(CLPlacemark *)placemark {
    MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
    point.coordinate = CLLocationCoordinate2DMake(placemark.location.coordinate.latitude, placemark.location.coordinate.longitude);
    point.title = [placemark.addressDictionary objectForKey:@"Street"];
    point.subtitle = [placemark.addressDictionary objectForKey:@"City"];
    [self.mapView addAnnotation:point];
}



-(void)showRoute:(MKDirectionsResponse *)response{

    for (MKRoute *route in response.routes)
    {
        [_mapView
         addOverlay:route.polyline level:MKOverlayLevelAboveRoads];

        for (MKRouteStep *step in route.steps){
            NSLog(@"%@",step.instructions);
        }



    }

}

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
    // If it's the user location, just return nil.
    if ([annotation isKindOfClass:[MKUserLocation class]])
        return nil;
    // Handle any custom annotations.
    if ([annotation isKindOfClass:[MKPointAnnotation class]]) {
        // Try to dequeue an existing pin view first.
        MKPinAnnotationView *pinView = (MKPinAnnotationView*)[self.mapView dequeueReusableAnnotationViewWithIdentifier:@"CustomPinAnnotationView"];
        if (!pinView)
        {
            // If an existing pin view was not available, create one.
            pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"CustomPinAnnotationView"];
            pinView.canShowCallout = YES;
        } else {
            pinView.annotation = annotation;
        }
        return pinView;
    }
    return nil;
}
-(void)getRoute {
    [self getLocationFromString];

    MKDirectionsRequest *directionsRequest = [[MKDirectionsRequest alloc] init];
    MKPlacemark *placemark = [[MKPlacemark alloc] initWithPlacemark:thePlacemark];
    [directionsRequest setSource:[MKMapItem mapItemForCurrentLocation]];
    [directionsRequest setDestination:[[MKMapItem alloc] initWithPlacemark:placemark]];
    directionsRequest.transportType = MKDirectionsTransportTypeAutomobile;
    MKDirections *directions = [[MKDirections alloc] initWithRequest:directionsRequest];
    [directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
        if (error) {
            NSLog(@"Error %@", error.description);
        } else {
            routeDetails = response.routes.lastObject;
            [self.mapView addOverlay:routeDetails.polyline];

        }
    }];
}
-(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
    MKPolylineRenderer  * routeLineRenderer = [[MKPolylineRenderer alloc] initWithPolyline:routeDetails.polyline];
    routeLineRenderer.strokeColor = [UIColor redColor];
    routeLineRenderer.lineWidth = 5;
    return routeLineRenderer;
}


- (IBAction)changeMapType:(id)sender {
    if (_mapView.mapType == MKMapTypeStandard)
        _mapView.mapType = MKMapTypeSatellite;
    else
        _mapView.mapType = MKMapTypeStandard;
}


-(void)getLocationFromString{

    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    [geocoder geocodeAddressString:self.agendaEntry.address completionHandler:^(NSArray *placemarks, NSError *error) {
        if (error) {
            NSLog(@"%@", error);
        } else {
            thePlacemark = [placemarks lastObject];
            float spanX = 1.00725;
            float spanY = 1.00725;
            MKCoordinateRegion region;
            region.center.latitude = thePlacemark.location.coordinate.latitude;
            region.center.longitude = thePlacemark.location.coordinate.longitude;
            region.span = MKCoordinateSpanMake(spanX, spanY);
            [self.mapView setRegion:region animated:YES];
            [self addAnnotation:thePlacemark];
        }
    }];
}

@end

我对此比较陌生,所以其中一些可能是错误的。我想要的是当我按下一个按钮(在另一个视图中)时,“agendaEntry”会在 segue 上传递。它包含一个带有地址的字符串,该地址被前向地理编码,地图显示从用户位置到该字符串中地址的方向/路线。

我不知道如何让它显示驾驶/步行方向或让它显示多条路线。但对于初学者来说,如果它能够奏效,那就太好了。

4

1 回答 1

1

它不绘制路线的原因是路线请求是在完成处理程序块实际设置目标地标 ( )之前发出的。thePlacemarkgeocodeAddressString

请注意文档中的内容geocodeAddressString:completionHandler:

该方法将指定的位置数据异步提交给地理编码服务器并返回。

因此,即使getLocationFromString(which calls geocodeAddressString) 在方向请求之前被调用,执行也会在启动 (但未完成)getRoute后立即返回并继续。geocodeAddressString

因此,thePlacemark仍然是nilgetRoute设置时directionsRequest,您可能会收到错误记录,例如“方向不可用”。

为了解决这个问题,您可以将对方向请求设置代码的调用移动到完成处理程序块内部geocodeAddressString(在添加注释代码之后)。

为此需要改变三件事:

  1. viewDidLoad,做[self getLocationFromString]; 而不是 [self getRoute];
  2. getRoute中,删除对 的调用getLocationFromString
  3. getLocationFromString,完成处理程序块中,之后[self addAnnotation:thePlacemark];,做[self getRoute];


关于显示多条路线,首先您需要实际请求备用路线(默认为NO):

directionsRequest.requestsAlternateRoutes = YES;

您可能遇到的问题的另一部分是由于以下行rendererForOverlay

MKPolylineRenderer  * routeLineRenderer = [[MKPolylineRenderer alloc] 
    initWithPolyline:routeDetails.polyline];

它使用外部实例变量而不是overlay提供给委托方法的参数来创建折线渲染器。这基本上意味着委托方法仅适用于特定routeDetails.polyline的覆盖(routeDetails.polyline指向正确的叠加层。每条备用路线都是一条单独的折线,地图视图将为每条路线单独调用rendererForOverlay

相反,使用overlay参数创建折线渲染器(并首先检查是否overlayMKPolyline):

-(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
    if ([overlay isKindOfClass:[MKPolyline class]])
    {
        MKPolylineRenderer  * routeLineRenderer = 
            [[MKPolylineRenderer alloc] initWithPolyline:overlay];
        routeLineRenderer.strokeColor = [UIColor redColor];
        routeLineRenderer.lineWidth = 5;
        return routeLineRenderer;
    }

    return nil;
}

然后在 中getRoute,而不是这个:

routeDetails = response.routes.lastObject;
[self.mapView addOverlay:routeDetails.polyline];

调用showRoute您已有的方法来添加所有路由:

[self showRoute:response];
于 2014-02-25T14:49:21.643 回答