Authored by Thomas Rasch

o Don't recreate the map view on tilesource changes (issue #47)

... ... @@ -28,6 +28,8 @@
@property (nonatomic, assign) BOOL useSnapshotRenderer;
@property (nonatomic, readonly) id <RMTileSource> tileSource;
- (id)initWithFrame:(CGRect)frame mapView:(RMMapView *)aMapView forTileSource:(id <RMTileSource>)aTileSource;
@end
... ...
... ... @@ -21,12 +21,13 @@
@implementation RMMapTiledLayerView
{
RMMapView *mapView;
id <RMTileSource> tileSource;
RMMapView *_mapView;
id <RMTileSource> _tileSource;
}
@synthesize delegate;
@synthesize useSnapshotRenderer;
@synthesize delegate = _delegate;
@synthesize useSnapshotRenderer = _useSnapshotRenderer;
@synthesize tileSource = _tileSource;
+ (Class)layerClass
{
... ... @@ -43,8 +44,8 @@
if (!(self = [super initWithFrame:frame]))
return nil;
mapView = [aMapView retain];
tileSource = [aTileSource retain];
_mapView = [aMapView retain];
_tileSource = [aTileSource retain];
self.userInteractionEnabled = YES;
self.multipleTouchEnabled = YES;
... ... @@ -53,8 +54,8 @@
self.useSnapshotRenderer = NO;
CATiledLayer *tiledLayer = [self tiledLayer];
size_t levelsOf2xMagnification = mapView.tileSourcesContainer.maxZoom;
if (mapView.adjustTilesForRetinaDisplay) levelsOf2xMagnification += 1;
size_t levelsOf2xMagnification = _mapView.tileSourcesContainer.maxZoom;
if (_mapView.adjustTilesForRetinaDisplay) levelsOf2xMagnification += 1;
tiledLayer.levelsOfDetail = levelsOf2xMagnification;
tiledLayer.levelsOfDetailBias = levelsOf2xMagnification;
... ... @@ -85,10 +86,10 @@
- (void)dealloc
{
[tileSource cancelAllDownloads];
[_tileSource cancelAllDownloads];
self.layer.contents = nil;
[tileSource release]; tileSource = nil;
[mapView release]; mapView = nil;
[_tileSource release]; _tileSource = nil;
[_mapView release]; _mapView = nil;
[super dealloc];
}
... ... @@ -109,7 +110,7 @@
if (self.useSnapshotRenderer)
{
zoom = (short)ceilf(mapView.adjustedZoomForRetinaDisplay);
zoom = (short)ceilf(_mapView.adjustedZoomForRetinaDisplay);
CGFloat rectSize = bounds.size.width / powf(2.0, (float)zoom);
int x1 = floor(rect.origin.x / rectSize),
... ... @@ -119,7 +120,7 @@
// NSLog(@"Tiles from x1:%d, y1:%d to x2:%d, y2:%d @ zoom %d", x1, y1, x2, y2, zoom);
if (zoom >= tileSource.minZoom && zoom <= tileSource.maxZoom)
if (zoom >= _tileSource.minZoom && zoom <= _tileSource.maxZoom)
{
UIGraphicsPushContext(context);
... ... @@ -127,7 +128,7 @@
{
for (int y=y1; y<=y2; ++y)
{
UIImage *tileImage = [tileSource imageForTile:RMTileMake(x, y, zoom) inCache:[mapView tileCache]];
UIImage *tileImage = [_tileSource imageForTile:RMTileMake(x, y, zoom) inCache:[_mapView tileCache]];
[tileImage drawInRect:CGRectMake(x * rectSize, y * rectSize, rectSize, rectSize)];
}
}
... ... @@ -146,12 +147,12 @@
UIImage *tileImage = nil;
if (zoom >= tileSource.minZoom && zoom <= tileSource.maxZoom)
tileImage = [tileSource imageForTile:RMTileMake(x, y, zoom) inCache:[mapView tileCache]];
if (zoom >= _tileSource.minZoom && zoom <= _tileSource.maxZoom)
tileImage = [_tileSource imageForTile:RMTileMake(x, y, zoom) inCache:[_mapView tileCache]];
if ( ! tileImage)
{
if (mapView.missingTilesDepth == 0)
if (_mapView.missingTilesDepth == 0)
{
tileImage = [RMTileImage errorTile];
}
... ... @@ -160,14 +161,14 @@
NSUInteger currentTileDepth = 1, currentZoom = zoom - currentTileDepth;
// tries to return lower zoom level tiles if a tile cannot be found
while ( !tileImage && currentZoom >= tileSource.minZoom && currentTileDepth <= mapView.missingTilesDepth)
while ( !tileImage && currentZoom >= _tileSource.minZoom && currentTileDepth <= _mapView.missingTilesDepth)
{
float nextX = x / powf(2.0, (float)currentTileDepth),
nextY = y / powf(2.0, (float)currentTileDepth);
float nextTileX = floor(nextX),
nextTileY = floor(nextY);
tileImage = [tileSource imageForTile:RMTileMake((int)nextTileX, (int)nextTileY, currentZoom) inCache:[mapView tileCache]];
tileImage = [_tileSource imageForTile:RMTileMake((int)nextTileX, (int)nextTileY, currentZoom) inCache:[_mapView tileCache]];
if (tileImage)
{
... ... @@ -192,7 +193,7 @@
}
}
if (mapView.debugTiles)
if (_mapView.debugTiles)
{
UIGraphicsBeginImageContext(tileImage.size);
... ... @@ -238,34 +239,34 @@
- (void)handleSingleTap:(UIGestureRecognizer *)recognizer
{
if ([delegate respondsToSelector:@selector(mapTiledLayerView:singleTapAtPoint:)])
[delegate mapTiledLayerView:self singleTapAtPoint:[recognizer locationInView:mapView]];
if ([_delegate respondsToSelector:@selector(mapTiledLayerView:singleTapAtPoint:)])
[_delegate mapTiledLayerView:self singleTapAtPoint:[recognizer locationInView:_mapView]];
}
- (void)handleTwoFingerSingleTap:(UIGestureRecognizer *)recognizer
{
if ([delegate respondsToSelector:@selector(mapTiledLayerView:twoFingerSingleTapAtPoint:)])
[delegate mapTiledLayerView:self twoFingerSingleTapAtPoint:[recognizer locationInView:mapView]];
if ([_delegate respondsToSelector:@selector(mapTiledLayerView:twoFingerSingleTapAtPoint:)])
[_delegate mapTiledLayerView:self twoFingerSingleTapAtPoint:[recognizer locationInView:_mapView]];
}
- (void)handleLongPress:(UILongPressGestureRecognizer *)recognizer
{
if (recognizer.state != UIGestureRecognizerStateBegan) return;
if ([delegate respondsToSelector:@selector(mapTiledLayerView:longPressAtPoint:)])
[delegate mapTiledLayerView:self longPressAtPoint:[recognizer locationInView:mapView]];
if ([_delegate respondsToSelector:@selector(mapTiledLayerView:longPressAtPoint:)])
[_delegate mapTiledLayerView:self longPressAtPoint:[recognizer locationInView:_mapView]];
}
- (void)handleDoubleTap:(UIGestureRecognizer *)recognizer
{
if ([delegate respondsToSelector:@selector(mapTiledLayerView:doubleTapAtPoint:)])
[delegate mapTiledLayerView:self doubleTapAtPoint:[recognizer locationInView:mapView]];
if ([_delegate respondsToSelector:@selector(mapTiledLayerView:doubleTapAtPoint:)])
[_delegate mapTiledLayerView:self doubleTapAtPoint:[recognizer locationInView:_mapView]];
}
- (void)handleTwoFingerDoubleTap:(UIGestureRecognizer *)recognizer
{
if ([delegate respondsToSelector:@selector(mapTiledLayerView:twoFingerDoubleTapAtPoint:)])
[delegate mapTiledLayerView:self twoFingerDoubleTapAtPoint:[recognizer locationInView:mapView]];
if ([_delegate respondsToSelector:@selector(mapTiledLayerView:twoFingerDoubleTapAtPoint:)])
[_delegate mapTiledLayerView:self twoFingerDoubleTapAtPoint:[recognizer locationInView:_mapView]];
}
@end
... ...
... ... @@ -1411,7 +1411,30 @@
[self setZoom:[self zoom]]; // setZoom clamps zoom level to min/max limits
// Recreate the map layer
NSUInteger tileSourcesContainerSize = [[_tileSourcesContainer tileSources] count];
if (tileSourcesContainerSize == 1)
{
[self createMapView];
}
else
{
int tileSideLength = [_tileSourcesContainer tileSideLength];
CGSize contentSize = CGSizeMake(tileSideLength, tileSideLength); // zoom level 1
RMMapTiledLayerView *tiledLayerView = [[RMMapTiledLayerView alloc] initWithFrame:CGRectMake(0.0, 0.0, contentSize.width, contentSize.height) mapView:self forTileSource:newTileSource];
tiledLayerView.delegate = self;
if (self.adjustTilesForRetinaDisplay && _screenScale > 1.0)
((CATiledLayer *)tiledLayerView.layer).tileSize = CGSizeMake(tileSideLength * 2.0, tileSideLength * 2.0);
else
((CATiledLayer *)tiledLayerView.layer).tileSize = CGSizeMake(tileSideLength, tileSideLength);
if (index >= [[_tileSourcesContainer tileSources] count])
[_tiledLayersSuperview addSubview:tiledLayerView];
else
[_tiledLayersSuperview insertSubview:tiledLayerView atIndex:index];
}
[self setCenterProjectedPoint:centerPoint animated:NO];
}
... ... @@ -1429,8 +1452,20 @@
_constrainMovement = NO;
}
// Recreate the map layer
[self createMapView];
// Remove the map layer
RMMapTiledLayerView *tileSourceTiledLayerView = nil;
for (RMMapTiledLayerView *tiledLayerView in _tiledLayersSuperview.subviews)
{
if (tiledLayerView.tileSource == tileSource)
{
tileSourceTiledLayerView = tiledLayerView;
break;
}
}
tileSourceTiledLayerView.layer.contents = nil;
[tileSourceTiledLayerView removeFromSuperview]; [tileSourceTiledLayerView release]; tileSourceTiledLayerView = nil;
[self setCenterProjectedPoint:centerPoint animated:NO];
}
... ... @@ -1448,20 +1483,29 @@
_constrainMovement = NO;
}
// Recreate the map layer
[self createMapView];
// Remove the map layer
RMMapTiledLayerView *tileSourceTiledLayerView = [_tiledLayersSuperview.subviews objectAtIndex:index];
tileSourceTiledLayerView.layer.contents = nil;
[tileSourceTiledLayerView removeFromSuperview]; [tileSourceTiledLayerView release]; tileSourceTiledLayerView = nil;
[self setCenterProjectedPoint:centerPoint animated:NO];
}
- (void)moveTileSourceAtIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex
{
if (fromIndex == toIndex)
return;
if (fromIndex >= [[_tileSourcesContainer tileSources] count])
return;
RMProjectedPoint centerPoint = [self centerProjectedPoint];
[_tileSourcesContainer moveTileSourceAtIndex:fromIndex toIndex:toIndex];
// Recreate the map layer
[self createMapView];
// Move the map layer
[_tiledLayersSuperview exchangeSubviewAtIndex:fromIndex withSubviewAtIndex:toIndex];
[self setCenterProjectedPoint:centerPoint animated:NO];
}
... ...
... ... @@ -17,6 +17,7 @@
#import "RMAnnotation.h"
#import "RMQuadTree.h"
#import "RMCoordinateGridSource.h"
#import "RMOpenCycleMapSource.h"
@implementation MainViewController
{
... ... @@ -170,16 +171,21 @@
// double delayInSeconds = 5.0;
// dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
// dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// [mapView addTileSource:[[[RMOpenSeaMapLayer alloc] init] autorelease]];
// dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
// [mapView addTileSource:[[[RMCoordinateGridSource alloc] init] autorelease]];
//
// dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
// dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
// [mapView setHidden:YES forTileSourceAtIndex:1];
//
// dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
// dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
// [mapView setHidden:NO forTileSourceAtIndex:1];
//
// dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
// dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
// [mapView removeTileSourceAtIndex:1];
// });
// });
// });
// });
... ...