3

私はこの機能を持っています:

- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context
{
    TileOverlay *tileOverlay = (TileOverlay *)self.overlay;
    NSArray *tilesInRect = [tileOverlay tilesInMapRect:mapRect zoomScale:zoomScale];
    CGContextSetAlpha(context, tileAlpha);

    for (ImageTile *tile in tilesInRect)
    {
        __block UIImage * image;
        CGRect rect = [self rectForMapRect:tile.frame];

            NSString *path = [[NSString alloc] initWithFormat:@".../%@.png", tile.imagePath];
            NSLog(@"Loading tile from URL %@", path);
            image =[UIImage imageWithData: [NSData dataWithContentsOfURL:[NSURL URLWithString: path]]];

            CGContextSaveGState(context);
            CGContextTranslateCTM(context, CGRectGetMinX(rect), CGRectGetMinY(rect));
            CGContextScaleCTM(context, 1/zoomScale, 1/zoomScale);
            CGContextTranslateCTM(context, 0, image.size.height);
            CGContextScaleCTM(context, 1, -1);
            CGContextDrawImage(context, CGRectMake(0, 0, image.size.width, image.size.height), [image CGImage]);
            CGContextRestoreGState(context);
    }
}

ご存じのようdataWithContentsOfURLに、スレッドが完了するまでスレッドをブロックします。セクションに画像読み込みブロックを追加したいGCD

私はこのようにそれをやろうとしました:

- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context
{
    TileOverlay *tileOverlay = (TileOverlay *)self.overlay;
    NSArray *tilesInRect = [tileOverlay tilesInMapRect:mapRect zoomScale:zoomScale];
    CGContextSetAlpha(context, tileAlpha);

    for (ImageTile *tile in tilesInRect)
    {
        __block UIImage * image;
        CGRect rect = [self rectForMapRect:tile.frame];

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0), ^{
            NSString *path = [[NSString alloc] initWithFormat:@".../%@.png", tile.imagePath];
            NSLog(@"Loading tile from URL %@", path);
            image =[UIImage imageWithData: [NSData dataWithContentsOfURL:[NSURL URLWithString: path]]];

            CGContextSaveGState(context);
            CGContextTranslateCTM(context, CGRectGetMinX(rect), CGRectGetMinY(rect));
            CGContextScaleCTM(context, 1/zoomScale, 1/zoomScale);
            CGContextTranslateCTM(context, 0, image.size.height);
            CGContextScaleCTM(context, 1, -1);
            CGContextDrawImage(context, CGRectMake(0, 0, image.size.width, image.size.height), [image CGImage]);
            CGContextRestoreGState(context);
        });
    }
}

しかし、コンテキストエラーが発生しました。このようなことで私を助けてください。GCD ブロックでコンテキスト操作を使用するには?

4

1 に答える 1

4

私の最初のメモは、 MKOverlayView が減価償却されていることです。MKOverlayRenderer への切り替えを検討する必要があります。

-draw_ _メソッド内から GCD を使用する必要がある状況はありません。これには、MKOverlayView -drawMapRect:zoomScale:inContext: と UIView -drawRect: が含まれます。代わりに、NSOperationQueue を -canDrawMapRect:zoomScale:zoomScale および setNeedsDisplayInMapRect: と組み合わせて使用​​する必要があります。

そのためのsudoコードは次のとおりです。

- (BOOL)canDrawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale
{
    BOOL hasAtLeastOneTile = NO;
    TileOverlay *tileOverlay = (TileOverlay *)self.overlay;
    NSArray *tilesInRect = [tileOverlay tilesInMapRect:mapRect zoomScale:zoomScale];

    for (ImageTile *tile in tilesInRect) {
        if ([tile isAvailable]) {
            hasAtLeastOneTile = hasAtLeastOneTile || YES;
        } else {
            // Add operation to NSOperationQueue to fetch tile
            __weak MKOverlayView *weakOverlay = self; // Weak ref to prevent retain cycles
            NSOperation *op = [NSBlockOperation blockOperationWithBlock: ^{
                //TODO: Load Tile
                [weakOverlay setNeedsDisplayInMapRect:mapRect];
            }];
            [self.operationQueue addOperation:op];
        }
    }
    return hasAtLeastOneTile;
}

次に、 -drawMapRect:zoomScale:inContext: で、利用可能なタイルを描画し、利用できないタイルをスキップします。

于 2013-10-18T13:21:17.787 に答える