Ios drawMapRect上下文+;中央大调度

Ios drawMapRect上下文+;中央大调度,ios,objective-c,mapkit,grand-central-dispatch,Ios,Objective C,Mapkit,Grand Central Dispatch,我有这个功能: - (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context { TileOverlay *tileOverlay = (TileOverlay *)self.overlay; NSArray *tilesInRect = [tileOverlay tilesInMapRect:mapRect zoomScale:zoo

我有这个功能:

- (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块中使用上下文操作?

我的第一个注意事项是MKOVERYVIEW已折旧。您应该考虑切换到MKOFLADRIENDER。

在任何情况下,都不应该从-draw_u_;方法中使用GCD。这包括MKOverlayView-drawMapRect:zoomScale:inContext:以及UIView-drawMapRect:。相反,您应该将NSOperationQueue与-canDrawMapRect:zoomScale:zoomScale和setNeedsDisplayinPrect:结合使用

下面是一些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中:你绘制可用的分幅,并跳过不可用的分幅。

你不能在主(UI)线程之外绘制,但我可以并行线程下载,然后更新,是吗?是的,你将需要发送到主线程非常有用,谢谢。如果可能的话,请回答一些愚蠢的问题=)我需要检查drawMapRect中是否有磁砖,是吗?所以我需要一些图像阵列(或地图)与所有瓷砖?还有其他问题:如果tile不可用并且现在已经下载,它会在drawMapRect中自动更新吗?谢谢你的时间,你应该已经有了任何你想画的东西。这通常意味着您将平铺存储在某种类型的数据结构中,例如NSMutableDictionary。此外,当您调用-setNeedsDisplayinPrect:,它将触发您通过调用-drawMapRect:zoomScale:inContext:指定的区域的重绘。您不应该直接调用-drawMapRect:zoomScale:inContext:yourself。