地图视图显示我的位置和目的地,但不显示它们之间的方向



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

这是我的代码:

#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上传递。它包含一个带有地址的字符串,该地址被向前地理编码,地图显示从用户所在地到该字符串中地址的方向/路线。

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

它之所以不绘制方向,是因为方向请求是在目标占位符(thePlacemark)实际上由geocodeAddressString完成处理程序块设置之前发出的。

注意文档中关于geocodeAddressString:completionHandler::的说明

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

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

因此,当getRoute设置directionsRequest时,thePlacemark仍然是nil,并且您可能会记录一个错误,例如"方向不可用"。

为此,您可以将对directions请求设置代码的调用移动到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参数创建多段线渲染器(首先检查overlay是否为MKPolyline):

-(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];

相关内容

  • 没有找到相关文章

最新更新