I use custom MKOverlay/MKOverlayView to completely cover the Google MKOverlay/MKOverlayView my own fragments that load asynchronously. I follow the unloaded slab request pattern when I get a call to canDrawMapRect:zoomScale: to my overlay view (and in this case return FALSE) and then calling setNeedsDisplayInMapRect:zoomScale: after it is available.
This generally works and seems to work great in a simulator.
However, on the device I sometimes get a βholeβ in the overlay - a missing fragment.
I see that the fragment is being requested and the request is being completed. I see what I call setNeedsDisplayInMapRect:zoomScale: and pass in the original MKMapRect and MKZoomScale that were provided in canDrawMapRect:zoomScale: But I also see that the overlay is never asked to redraw this tile (none of canDrawMapRect:zoomScale: and drawMapRect:zoomScale:inContext: again called for this tile).
I need to understand why this is happening and how to fix it.
Here is the relevant code from my subclass of 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]; }
EDIT : I guess this is most likely a problem.
ios mapkit mkmapview mkoverlay
Tomswift
source share