当我初始化地图时,它会显示我的位置和目的地(从字符串进行地理编码),但它不会在它们之间绘制方向。
这是我的代码:
#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上传递。它包含一个带地址的字符串,该地址进行前向地理编码,地图显示从用户位置到该字符串中地址的路线/路线。
我不知道如何让它显示驾驶/步行路线或让它显示多条路线。但对于初学者来说,如果能够奏效将会很棒。
答案 0 :(得分:1)
它没有绘制路线的原因是因为在目标地标(thePlacemark
)实际由geocodeAddressString
完成处理程序块设置之前正在进行路线请求
请注意文档中有关geocodeAddressString:completionHandler:
的内容:
此方法异步将指定的位置数据提交给地理编码服务器并返回。
因此,即使在方向请求之前调用getLocationFromString
(调用geocodeAddressString
),执行也会在getRoute
启动后立即返回并继续geocodeAddressString
(但不是完成)。
因此,当thePlacemark
设置nil
时,getRoute
仍为directionsRequest
,您可能会收到错误信息,例如“路线不可用”。
为了解决这个问题,您可以将调用方向请求设置代码移动到内部 geocodeAddressString
完成处理程序块(在添加注释代码之后)。
有三件事需要改变:
viewDidLoad
中,执行[self getLocationFromString];
而不是 [self getRoute];
。getRoute
,删除对getLocationFromString
的号召。getLocationFromString
中,在完成处理程序块中,在[self addAnnotation:thePlacemark];
之后,执行[self getRoute];
。
关于显示多条路线,首先您需要实际请求备用路线(默认为NO
):
directionsRequest.requestsAlternateRoutes = YES;
您可能遇到的问题的另一部分是rendererForOverlay
中的这一行:
MKPolylineRenderer * routeLineRenderer = [[MKPolylineRenderer alloc]
initWithPolyline:routeDetails.polyline];
它使用外部实例变量而不是提供给委托方法的overlay
参数创建折线渲染器。这基本上意味着委托方法仅适用于那个特定的覆盖(routeDetails.polyline
),并且由于无法控制地图视图何时调用委托方法,因此无法可靠地设置{{1}从委托方法外部确保它指向正确的叠加层。每个备用路线都是单独的折线,地图视图会为每个路线单独调用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