我正在使用自定义MKOverlay/MKOverlayView
用我自己的图块完全覆盖Google basemap ,这些图块是异步加载的。当我收到对覆盖 View 的canDrawMapRect:zoomScale:
调用(并在这种情况下返回FALSE)时,我遵循请求卸载图块的模式,然后在图块可用时调用setNeedsDisplayInMapRect:zoomScale:
。
所有这些通常都可以正常运行,并且在模拟器中似乎可以完美运行。
但是,在设备上有时会在覆盖层上出现“洞”-缺少瓷砖。
我可以看到该图块已请求,并且请求已完成。我可以看到我叫setNeedsDisplayInMapRect:zoomScale:
,并且传递了MKMapRect
中提供的原始MKZoomScale
和canDrawMapRect:zoomScale:
。但我也可以看到,从未要求覆盖层重绘该图块(不再为该图块调用canDrawMapRect:zoomScale:
和drawMapRect:zoomScale:inContext:
)。
我需要了解为什么会发生这种情况以及如何纠正它。
这是我的MKOverlayView子类中的相关代码:
- (BOOL) canDrawMapRect: (MKMapRect) mapRect zoomScale: (MKZoomScale) zoomScale
{
NSUInteger zoomLevel = [self zoomLevelForZoomScale:zoomScale];
CGPoint mercatorPoint = [self mercatorTileOriginForMapRect:mapRect];
NSUInteger tilex = floor(mercatorPoint.x * [self worldTileWidthForZoomLevel:zoomLevel]);
NSUInteger tiley = floor(mercatorPoint.y * [self worldTileWidthForZoomLevel:zoomLevel]);
NSURL* tileUrl = [self tileURLForZoomLevel: zoomLevel tileX: tilex tileY: tiley];
ASIHTTPRequest* tileRequest = [ASIHTTPRequest requestWithURL: tileUrl];
tileRequest.downloadCache = [ASIDownloadCache sharedCache];
[tileRequest setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
if ( NO == [[ASIDownloadCache sharedCache] isCachedDataCurrentForRequest: tileRequest] )
{
[tileRequest setCachePolicy: ASIAskServerIfModifiedWhenStaleCachePolicy];
tileRequest.delegate = self;
tileRequest.userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
[NSValue value: &mapRect withObjCType: @encode( MKMapRect )], @"mapRect",
[NSValue value: &zoomScale withObjCType: @encode( MKZoomScale )], @"zoomScale",
[NSNumber numberWithInt: tilex], @"tilex",
[NSNumber numberWithInt: tiley], @"tiley",
nil];
[_tileRequestStack addOperation: tileRequest];
NSLog( @"canDrawMapRect: %d, %d - REQUESTING", tilex, tiley );
return NO;
}
NSLog( @"canDrawMapRect: %d, %d - READY", tilex, tiley );
return YES;
}
- (void) drawMapRect: (MKMapRect) mapRect zoomScale: (MKZoomScale) zoomScale inContext: (CGContextRef) context
{
NSUInteger zoomLevel = [self zoomLevelForZoomScale:zoomScale];
CGPoint mercatorPoint = [self mercatorTileOriginForMapRect:mapRect];
NSUInteger tilex = floor(mercatorPoint.x * [self worldTileWidthForZoomLevel:zoomLevel]);
NSUInteger tiley = floor(mercatorPoint.y * [self worldTileWidthForZoomLevel:zoomLevel]);
NSLog( @"drawMapRect: %d, %d", tilex, tiley );
NSURL* tileUrl = [self tileURLForZoomLevel: zoomLevel tileX: tilex tileY: tiley];
NSData* tileData = [[ASIDownloadCache sharedCache] cachedResponseDataForURL: tileUrl];
UIGraphicsPushContext(context);
if ( tileData != nil )
{
UIImage* img = [UIImage imageWithData: tileData];
if ( img != nil )
{
[img drawInRect: [self rectForMapRect: mapRect] blendMode: kCGBlendModeNormal alpha: 1.0 ];
}
else
{
NSLog( @"oops - no image" );
}
CGSize s = CGContextConvertSizeToUserSpace( context, CGSizeMake( 40, 1 ));
UIFont* f = [UIFont systemFontOfSize: s.width];
[[UIColor blackColor] setFill];
[[NSString stringWithFormat: @"%d,%d", tilex, tiley] drawInRect: [self rectForMapRect: mapRect] withFont: f];
}
UIGraphicsPopContext();
}
- (void) requestFinished: (ASIHTTPRequest *) tileRequest
{
NSValue* mapRectValue = [tileRequest.userInfo objectForKey: @"mapRect"];
MKMapRect mapRect; [mapRectValue getValue: &mapRect];
NSValue *zoomScaleValue = [tileRequest.userInfo objectForKey:@"zoomScale"];
MKZoomScale zoomScale; [zoomScaleValue getValue: &zoomScale];
NSLog( @"requestFinished: %d, %d, %lf",
[[tileRequest.userInfo objectForKey:@"tilex"] intValue],
[[tileRequest.userInfo objectForKey:@"tiley"] intValue],
zoomScale );
[self setNeedsDisplayInMapRect: mapRect zoomScale: zoomScale];
}
编辑:I'm guessing that this is likely the issue.
最佳答案
我遇到的问题与此处描述的问题非常相似。就我而言,即使拥有最简单的代码,我也无法重现所需的行为(在http://developer.apple.com/library/ios/documentation/MapKit/Reference/MKOverlayView_class/Reference/Reference.html#//apple_ref/occ/instm/MKOverlayView/setNeedsDisplayInMapRect:zoomScale:中描述):
- (BOOL)canDrawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale {
NSLog(@"This should trace forever");
[self setNeedsDisplayInMapRect:mapRect zoomScale:zoomScale];
return NO;
}
或更接近我的原始代码:
- (BOOL)canDrawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale {
NSLog(@"This should trace forever");
[SomeAsynchronousRequestWithCompletionHandler:^{
[self setNeedsDisplayInMapRect:mapRect zoomScale:zoomScale];
}];
return NO;
}
在这两种情况下,setNeedsDisplayInMapRect:zoomScale:都从未被调用过。
当我开始运行setNeedsDisplayInMapRect:zoomScale:时,情况发生了变化,在dispatch_async内分派(dispatch)到可以运行canDrawMapRect的相同队列,例如:
- (BOOL)canDrawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale {
dispatch_queue_t queue = dispatch_get_current_queue();
NSLog(@"This should trace forever");
dispatch_async(queue, ^{
[self setNeedsDisplayInMapRect:mapRect zoomScale:zoomScale];
});
return NO;
}
或包含异步作业:
- (BOOL)canDrawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale {
NSLog(@"This should trace forever");
dispatch_queue_t queue = dispatch_get_current_queue();
[SomeAsynchronousRequestWithCompletionHandler:^{
dispatch_async(queue, ^{
[self setNeedsDisplayInMapRect:mapRect zoomScale:zoomScale];
});
}];
return NO;
}
使用dispatch_async-我可以看到不断跟踪的“这应该永远跟踪”字符串。我原来的问题也完全消失了。
最新消息:目前,我使用dispatch_get_main_queue()调用setNeedsDisplayInMapRect:zoomScale:
- (BOOL)canDrawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale {
NSLog(@"This should trace forever");
[SomeAsynchronousRequestWithCompletionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
[self setNeedsDisplayInMapRect:mapRect zoomScale:zoomScale];
});
}];
return NO;
}