尝试在MKMapkit上执行WMS磁贴作为自定义叠加层。我创建了一个MKOverlay模式,从我们的服务器检索一个tile并将它们存储在对象的NSCache中:
- (CLLocationCoordinate2D)coordinate
{
return MKCoordinateForMapPoint(MKMapPointMake(MKMapRectGetMidX(boundingMapRect),
MKMapRectGetMidY(boundingMapRect)));
}
- (MKMapRect)boundingMapRect
{
return boundingMapRect;
}
- (NSArray *)tilesInMapRect:(MKMapRect)rect zoomScale:(MKZoomScale)scale
{
NSInteger z = zoomScaleToZoomLevel(scale);
// Number of tiles wide or high (but not wide * high)
NSInteger tilesAtZ = pow(2, z);
NSInteger minX = floor((MKMapRectGetMinX(rect) * scale) / TILE_SIZE);
NSInteger maxX = floor((MKMapRectGetMaxX(rect) * scale) / TILE_SIZE);
NSInteger minY = floor((MKMapRectGetMinY(rect) * scale) / TILE_SIZE);
NSInteger maxY = floor((MKMapRectGetMaxY(rect) * scale) / TILE_SIZE);
//NSLog(@"minX: %d maxX: %d minY: %d, maxY: %d", minX, maxX, minY, maxY);
NSMutableArray *tiles = nil;
for (NSInteger x = minX; x <= maxX; x++) {
for (NSInteger y = minY; y <= maxY; y++) {
// As in initWithTilePath, need to flip y index to match the gdal2tiles.py convention.
NSInteger flippedY = abs(y + 1 - tilesAtZ);
NSString *tileKey = [[NSString alloc] initWithFormat:@"%d+%d+%d", z, x, flippedY];
//NSLog(@"tilekey: %@", tileKey);
if ([self.tileCache objectForKey:tileKey])
{
if (!tiles) {
tiles = [NSMutableArray array];
}
MKMapRect frame = MKMapRectMake((double)(x * TILE_SIZE) / scale,
(double)(y * TILE_SIZE) / scale,
TILE_SIZE / scale,
TILE_SIZE / scale);
ImageTile *tile = [[ImageTile alloc] initWithFrame:frame path:[self.tileCache objectForKey:tileKey]];
[tiles addObject:tile];
}
}
}
return tiles;
}
我有其他方法可以找到google tile(x,y,z)并进行WMS调用。
我查看过苹果公司的TileMap示例并借鉴了他们的代码。
我创建了一个MKOverlayView并覆盖了canDrawMapRect和drawMapRect:
//EDIT: added the init method
- (id)initWithOverlay:(id <MKOverlay>)overlay
{
if (self = [super initWithOverlay:overlay]) {
tileAlpha = 0.75;
}
return self;
}
- (BOOL)canDrawMapRect:(MKMapRect)mapRect
zoomScale:(MKZoomScale)zoomScale
{
TileOverlay *tileOverlay = (TileOverlay *)self.overlay;
NSArray *tilesInRect = [tileOverlay tilesInMapRect:mapRect zoomScale:zoomScale];
if ([tilesInRect count] > 0)
{
return YES;
}
else
{
[tileOverlay retrieveWMSTileWithMapRect:mapRect zoomScale:zoomScale];
return NO;
}
}
- (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) {
// For each image tile, draw it in its corresponding MKMapRect frame
CGRect rect = [self rectForMapRect:tile.imageFrame];
UIImage *image = [[UIImage alloc] initWithData:tile.imageData];
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);
}
}
在我的MKMapKitViewController中,我创建了TileOverlay对象并将其添加到地图中:
- (void)viewDidLoad
{
[super viewDidLoad];
self.mapView.delegate = self;
self.mapView.mapType = MKMapTypeStandard;
TileOverlay *tileOverlay = [[TileOverlay alloc] init];
[self.mapView addOverlay:tileOverlay];
}
我还实现了mapView:viewForOverlay方法:
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
NSLog(@"viewForOverlay fired");
TileOverlayView *view = [[TileOverlayView alloc] initWithOverlay:overlay];
view.tileAlpha = 0.6;
return view;
}
问题是从不调用canDrawRect / drawRect。我错过了什么让这个工作?