Authored by devel-hb

Some handling for memory warnings.

RMMapContents now has a new method -(void) didReceiveMemoryWarning that 
may be called by the Controller in case a memory warning was issued.
It will clear the memory cache and reopen the database cache to purge
all buffered sqlite pages from memory.

No change in behavior unless this method is explicitly called.

... ... @@ -100,8 +100,10 @@
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
// due to a bug, RMMapView should never be released, as it causes the application to crash
//[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
[mapView.contents didReceiveMemoryWarning];
}
... ...
... ... @@ -69,5 +69,9 @@
return [RMProjection googleProjection];
}
-(void) didReceiveMemoryWarning
{
}
@end
... ...
... ... @@ -20,6 +20,7 @@
}
- (id) initWithSource: (id<RMTileSource>) source;
- (void) didReceiveMemoryWarning;
// Bleah ugly name.
+ (RMCachedTileSource*) cachedTileSourceWithSource: (id<RMTileSource>) source;
... ...
... ... @@ -84,4 +84,9 @@
return [tileSource maxZoom];
}
- (void) didReceiveMemoryWarning
{
[cache didReceiveMemoryWarning];
}
@end
... ...
... ... @@ -12,12 +12,15 @@
@class RMTileCacheDAO;
@interface RMDatabaseCache : NSObject<RMTileCache> {
NSString* databasePath;
RMTileCacheDAO *dao;
RMCachePurgeStrategy purgeStrategy;
NSUInteger capacity;
NSUInteger minimalPurge;
}
@property (retain) NSString* databasePath;
+ (NSString*)dbPathForTileSource: (id<RMTileSource>) source usingCacheDir: (BOOL) useCacheDir;
-(id) initWithDatabase: (NSString*)path;
-(id) initWithTileSource: (id<RMTileSource>) source usingCacheDir: (BOOL) useCacheDir;
... ...
... ... @@ -13,6 +13,8 @@
@implementation RMDatabaseCache
@synthesize databasePath;
+ (NSString*)dbPathForTileSource: (id<RMTileSource>) source usingCacheDir: (BOOL) useCacheDir
{
NSArray *paths;
... ... @@ -39,6 +41,7 @@
// NSLog(@"%d items in DB", [[DAO sharedManager] count]);
self.databasePath = path;
dao = [[RMTileCacheDAO alloc] initWithDatabase:path];
if (dao == nil)
... ... @@ -55,6 +58,8 @@
-(void) dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[databasePath release];
[dao release];
[super dealloc];
}
... ... @@ -94,15 +99,17 @@
NSData *data = [[notification userInfo] objectForKey:@"data"];
RMTileImage *image = (RMTileImage*)[notification object];
if (capacity != 0) {
NSUInteger tilesInDb = [dao count];
if (capacity <= tilesInDb) {
[dao purgeTiles: MAX(minimalPurge, 1+tilesInDb-capacity)];
@synchronized (self) {
if (capacity != 0) {
NSUInteger tilesInDb = [dao count];
if (capacity <= tilesInDb) {
[dao purgeTiles: MAX(minimalPurge, 1+tilesInDb-capacity)];
}
}
}
[dao addData:data LastUsed:[image lastUsedTime] ForTile:RMTileHash([image tile])];
[dao addData:data LastUsed:[image lastUsedTime] ForTile:RMTileHash([image tile])];
}
[[NSNotificationCenter defaultCenter] removeObserver:self
name:RMMapImageLoadedNotification
... ... @@ -115,13 +122,19 @@
-(RMTileImage*) cachedImage:(RMTile)tile
{
// NSLog(@"Looking for cached image in DB");
NSData *data = nil;
NSData *data = [dao dataForTile:RMTileHash(tile)];
if (data == nil)
return nil;
@synchronized (self) {
if (capacity != 0 && purgeStrategy == RMCachePurgeStrategyLRU) {
[dao touchTile: RMTileHash(tile) withDate: [NSDate date]];
data = [dao dataForTile:RMTileHash(tile)];
if (data == nil)
return nil;
if (capacity != 0 && purgeStrategy == RMCachePurgeStrategyLRU) {
[dao touchTile: RMTileHash(tile) withDate: [NSDate date]];
}
}
RMTileImage *image = [RMTileImage imageWithTile:tile FromData:data];
... ... @@ -129,4 +142,18 @@
return image;
}
-(void)didReceiveMemoryWarning
{
if (self.databasePath==nil) {
NSLog(@"unknown db path, unable to reinitialize dao!");
return;
}
@synchronized (self) {
[dao release];
dao = [[RMTileCacheDAO alloc] initWithDatabase:self.databasePath];
}
}
@end
... ...
... ... @@ -101,6 +101,8 @@ enum {
// Designated initialiser
- (id)initForView:(UIView*)view WithTileSource:(id<RMTileSource>)tileSource WithRenderer:(RMMapRenderer*)renderer LookingAt:(CLLocationCoordinate2D)latlong;
- (void) didReceiveMemoryWarning;
- (void)moveToLatLong: (CLLocationCoordinate2D)latlong;
- (void)moveToXYPoint: (RMXYPoint)aPoint;
... ...
... ... @@ -38,36 +38,22 @@
@synthesize markerManager;
#pragma mark Initialisation
- (id) initForView: (UIView*) view
{
id<RMTileSource> _tileSource = [[RMOpenStreetMapsSource alloc] init];
RMMapRenderer *_renderer = [[RMCoreAnimationRenderer alloc] initWithContent:self];
{
CLLocationCoordinate2D here;
here.latitude = -35;
here.longitude = 146.2381;
// here.latitude = 65.146;
// here.longitude = 189.9;
id mapContents = [self initForView:view WithTileSource:_tileSource WithRenderer:_renderer LookingAt:here];
[_tileSource release];
[_renderer release];
return mapContents;
return [self initForView:view WithLocation: here];
}
- (id) initForView: (UIView*) view WithLocation:(CLLocationCoordinate2D)latlong
{
id<RMTileSource> _tileSource = [[RMOpenStreetMapsSource alloc] init];
RMMapRenderer *_renderer = [[RMCoreAnimationRenderer alloc] initWithContent:self];
CLLocationCoordinate2D here;
here.latitude = latlong.latitude;
here.longitude = latlong.longitude;
// here.latitude = 65.146;
// here.longitude = 189.9;
id mapContents = [self initForView:view WithTileSource:_tileSource WithRenderer:_renderer LookingAt:here];
id mapContents = [self initForView:view WithTileSource:_tileSource WithRenderer:_renderer LookingAt:latlong];
[_tileSource release];
[_renderer release];
... ... @@ -144,6 +130,12 @@
[super dealloc];
}
- (void) didReceiveMemoryWarning
{
[tileSource didReceiveMemoryWarning];
}
#pragma mark Forwarded Events
- (void)moveToLatLong: (CLLocationCoordinate2D)latlong
... ... @@ -358,6 +350,8 @@
- (void) setBackground: (RMMapLayer*) aLayer
{
if (background == aLayer) return;
if (background != nil)
{
[background release];
... ... @@ -382,6 +376,8 @@
- (void) setOverlay: (RMLayerSet*) aLayer
{
if (overlay == aLayer) return;
if (overlay != nil)
{
[overlay release];
... ...
... ... @@ -44,6 +44,11 @@
[super dealloc];
}
-(void) didReceiveMemoryWarning
{
[cache removeAllObjects];
}
-(void) removeTile: (RMTile) tile
{
// NSLog(@"tile %d %d %d removed from cache", tile.x, tile.y, tile.zoom);
... ...
... ... @@ -22,6 +22,7 @@ typedef enum {
// Returns the cached image if it exists. nil otherwise.
-(RMTileImage*) cachedImage:(RMTile)tile;
-(void)didReceiveMemoryWarning;
@optional
... ... @@ -45,4 +46,6 @@ typedef enum {
// Add another cache to the chain
-(void)addCache: (id<RMTileCache>)cache;
-(void)didReceiveMemoryWarning;
@end
... ...
... ... @@ -112,6 +112,14 @@
}
}
-(void)didReceiveMemoryWarning
{
for (id<RMTileCache> cache in caches)
{
[cache didReceiveMemoryWarning];
}
}
@end
@implementation RMTileCache ( Configuration )
... ...
... ... @@ -27,4 +27,6 @@
-(float) minZoom;
-(float) maxZoom;
-(void) didReceiveMemoryWarning;
@end
... ...