1

MKMapView と MKPolyline を使用してルート形状を表示しています。注釈が MKMapView に配置され、そこに別の注釈が既に存在する場合、ルート プロバイダーにルーティング コールを非同期的にディスパッチし、成形されたオーバーレイを追加します。

これが問題です。リクエストにメイン スレッドを使用すると、リクエストの進行中に MKAnnotation ドロップがフリーズしますが、戻るとオーバーレイが適切に表示されます。代わりにリクエストを非同期キューにディスパッチすると、アノテーション ドロップがフリーズせず、非同期呼び出しが完了するとオーバーレイが追加されますが、MapView がそれを認識して実際にオーバーレイを描画するにはしばらく時間がかかります。20秒くらいかかる時もあります。これがコードです。

//Action handler selector to drop the pin
-(void)dropWayPoint:(WayPoint*)wp prevWayPoint:(WayPoint*)prevWp {
    [self.mapView addWayPoint: wp];
    [self.routeService routeFrom:prevWp to:wp];
}

実際のルート計算は次のとおりです。

@implementation RouteService

static dispatch_queue_t queue;

+(RouteService) initRouteService:(id)delegate {
    RouteService *rs = [[RouteService alloc] init];
    //Lots of things happen here, including the queue creation
    ...
    if (!queue) {
        queue = dispatch_queue_create("RouteDispatch.queue", NULL);
    }
    return rs;
}
//Lots of methods...
//then
-(void)routeFrom:(WayPoint*)wp to:(WayPoint*)wpTp {
    dispatch_async(queue, ^{
        //Code here
        DirectionsRouteRequest *rt = [DirectionsRouteRequest buildWithRouteType:@"fastest"];
        [rt addObjectToLocation:[wp coord]];
        [rt addObjectToLocation:[wpTp coord]];
        rt.options.routeType = @"fastest";

        NSLog(@"Dispatching...");

        //Now send the request
        DirectionsResponseType *response = [MapUtil computeDirections:rt];

        Leg *leg = [Leg buildFromResponse:response route: self.route startWayPoint:wp endWayPoint:wpTp];
        MKPolyline *pl = [MapUtil makePolylineWithLocations:[leg routeShape]];
        [self.route.legsHash setObject:pl forKey:leg.legIdStr];

        //Add Overlay here!!!
        [self.mapDeskViewController.mapView addOverlay: pl];
        //Desperately advising map view to redraw itself and show the overlay
        [self.mapDeskViewController.mapView setNeedsDisplay];

        //I can see this being displayed very quickly, meaning 
        NSLog(@"Response, pl_count:%d",pl.pointCount);

        //However it takes a long time after this returns to actually display the overlay.
    });
}

上記のコードを取得して async ディレクティブをコメント アウトすると、処理に同じ時間がかかり、迷惑なフリーズが発生しますが、オーバーレイはすぐに描画されます。

//Lots of methods...
//then
-(void)routeFrom:(WayPoint*)wp to:(WayPoint*)wpTp {
    /* COMMENTED OUT ASYNC
    dispatch_async(queue, ^{
    */
        //Code here
        DirectionsRouteRequest *rt = [DirectionsRouteRequest buildWithRouteType:@"fastest"];
        [rt addObjectToLocation:[wp coord]];
        [rt addObjectToLocation:[wpTp coord]];
        rt.options.routeType = @"fastest";

        NSLog(@"Dispatching...");

        //Now send the request
        DirectionsResponseType *response = [MapUtil computeDirections:rt];

        Leg *leg = [Leg buildFromResponse:response route: self.route startWayPoint:wp endWayPoint:wpTp];
        MKPolyline *pl = [MapUtil makePolylineWithLocations:[leg routeShape]];
        [self.route.legsHash setObject:pl forKey:leg.legIdStr];

        //Add Overlay here!!!
        [self.mapDeskViewController.mapView addOverlay: pl];
        //Desperately advising map view to redraw itself and show the overlay
        [self.mapDeskViewController.mapView setNeedsDisplay];

        //I can see this being displayed very quickly, meaning 
        NSLog(@"Response, pl_count:%d",pl.pointCount);
    /*
    COMMENTED OUT ASYNC
    });
    */
}

MKMapView が非同期で行われたときにオーバーレイを描画する必要があることに気付くのに時間がかかる理由は何ですか?

ありがとうアウレリオ

4

1 に答える 1

2

メイン スレッドでマップ ビュー (およびすべての UI) を更新する必要があります。したがって、dispatch_async ブロック内で応答を受け取った後:

   // Create another block that gets queued up in the main_queue, a default serial queue
   dispatch_async(dispatch_get_main_queue(), ^{

       Leg *leg = [Leg buildFromResponse:response route: self.route startWayPoint:wp endWayPoint:wpTp];
       MKPolyline *pl = [MapUtil makePolylineWithLocations:[leg routeShape]];
       [self.route.legsHash setObject:pl forKey:leg.legIdStr];

       //Add Overlay here!!!
       [self.mapDeskViewController.mapView addOverlay: pl];
       //Desperately advising map view to redraw itself and show the overlay
       [self.mapDeskViewController.mapView setNeedsDisplay];

       //I can see this being displayed very quickly, meaning 
       NSLog(@"Response, pl_count:%d",pl.pointCount);
    });
于 2012-09-09T02:25:42.193 に答える