ios - drawMapRect 上下文 + 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: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 阻塞线程直到完成。我想将图像加载 block 添加到 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 block 中使用上下文操作?

最佳答案

我的第一个注意事项是 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: 中绘制可用的图 block 并跳过不可用的图 block 。

关于ios - drawMapRect 上下文 + Grand Central Dispatch,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19449654/

相关文章:

ios - 如何在同一函数中再次调用部分代码?

ios - 错误 : unreachable because it has no entry points

objective-c - 动态生成枚举参数?

ios - MapKit - 在不占用大量 CPU 的情况下跟踪 map 上的用户位置

swift - Swift-在MKCircle中设置多个fillColor

ios - 如何为阿拉伯语希伯来语实现带 RTL 的 iOS?

ios - 不使用 UIDocument 获取 iCloud URL 的数据内容

iphone - 是否有 objective-c "equivalent"到 ruby​​ 的发送方法?

ios - 自定义字体不显示

ios - MKMapView 自行缩小