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」がセグエで渡されることです。住所を含む文字列が含まれており、この住所はフォワード ジオコーディングされ、地図にはユーザーの場所からその文字列の住所へのルートが表示されます。

ドライブ/徒歩のルート案内を表示する方法、または複数のルートを表示する方法がわかりません。しかし、まず、それが機能するなら素晴らしいことです。

4

1 に答える 1

1

ルート案内が描画されない理由は、目的地の目印 ( ) が完了ハンドラ ブロックによって実際に設定される前にルート案内リクエストが行われるためです。thePlacemarkgeocodeAddressString

ドキュメントの内容に注意してくださいgeocodeAddressString:completionHandler:

このメソッドは、指定された位置データを非同期でジオコーディング サーバーに送信し、返します。

したがって、ルート リクエストの前にgetLocationFromString( which を呼び出す) が呼び出されたとしても、実行は が開始された直後に返されて続行されます(ただし、完了していません)。geocodeAddressStringgetRoutegeocodeAddressString

そのため、まだthePlacemarkセットアップ中ですが、おそらく「方向が利用できません」などのエラーがログに記録されます。nilgetRoutedirectionsRequest

これを考慮して、direction-request-set-up コードへの呼び出しを完了ハンドラ ブロック内 (add-annotation コードの後) に移動できますgeocodeAddressString

これには、次の 3 つの変更点があります。

  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デリゲート メソッドに提供されるパラメーターの代わりに、外部インスタンス変数を使用してポリライン レンダラーを作成しています。これは基本的に、デリゲート メソッドがその 1 つの特定のオーバーレイ ( 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];
于 2014-02-25T14:49:21.643 に答える