Authored by Thomas Rasch

Merge branch 'develop' into release

... ... @@ -41,6 +41,8 @@
CLLocationCoordinate2D center;
}
@property (nonatomic, retain) NSString *uniqueTilecacheKey;
- (id)initWithPath:(NSString *)path;
- (CLLocationCoordinate2D)topLeftOfCoverage;
... ...
... ... @@ -98,14 +98,19 @@
@interface RMDBMapSource(PrivateMethods)
- (NSString *)getPreferenceAsString:(NSString *)name;
- (float)getPreferenceAsFloat:(NSString *)name;
- (int)getPreferenceAsInt:(NSString *)name;
@end
#pragma mark -
@implementation RMDBMapSource
@synthesize uniqueTilecacheKey;
- (id)initWithPath:(NSString *)path
{
if (!(self = [super init]))
... ... @@ -192,12 +197,12 @@
// fetch the image from the db
FMResultSet *result = [db executeQuery:@"SELECT image FROM tiles WHERE tilekey = ?", key];
FMDBErrorCheck(db);
UIImage *image = nil;
if ([result next]) {
image = [[[UIImage alloc] initWithData:[result dataNoCopyForColumn:@"image"]] autorelease];
image = [[[UIImage alloc] initWithData:[result dataForColumn:@"image"]] autorelease];
} else {
image = [UIImage imageNamed:@"nodata.png"];
image = [RMTileImage missingTile];
}
[result close];
... ...
... ... @@ -29,10 +29,18 @@
#import "RMTileCache.h"
@class RMTileCacheDAO;
@class FMDatabase;
@interface RMDatabaseCache : NSObject <RMTileCache> {
// Database
FMDatabase* db;
NSString *databasePath;
RMTileCacheDAO *dao;
NSUInteger tileCount;
NSOperationQueue *writeQueue;
NSRecursiveLock *writeQueueLock;
// Cache
RMCachePurgeStrategy purgeStrategy;
NSUInteger capacity;
NSUInteger minimalPurge;
... ...
... ... @@ -26,10 +26,23 @@
// POSSIBILITY OF SUCH DAMAGE.
#import "RMDatabaseCache.h"
#import "RMTileCacheDAO.h"
#import "FMDatabase.h"
#import "RMTileImage.h"
#import "RMTile.h"
#define kWriteQueueLimit 25
@interface RMDatabaseCache ()
- (NSUInteger)count;
- (NSUInteger)countTiles;
- (void)touchTile:(RMTile)tile withKey:(NSString *)cacheKey;
- (void)purgeTiles:(NSUInteger)count;
@end
#pragma mark -
@implementation RMDatabaseCache
@synthesize databasePath;
... ... @@ -62,20 +75,45 @@
return nil;
}
- (void)configureDBForFirstUse
{
[db executeQuery:@"PRAGMA synchronous=OFF"];
[db executeQuery:@"PRAGMA journal_mode=OFF"];
[db executeUpdate:@"CREATE TABLE IF NOT EXISTS ZCACHE (tile_hash INTEGER NOT NULL, cache_key VARCHAR(25) NOT NULL, last_used DOUBLE NOT NULL, data BLOB NOT NULL)"];
[db executeUpdate:@"CREATE UNIQUE INDEX IF NOT EXISTS main_index ON ZCACHE(tile_hash, cache_key)"];
[db executeUpdate:@"CREATE INDEX IF NOT EXISTS last_used_index ON ZCACHE(last_used)"];
}
- (id)initWithDatabase:(NSString *)path
{
if (!(self = [super init]))
return nil;
self.databasePath = path;
dao = [[RMTileCacheDAO alloc] initWithDatabase:path];
if (!dao) {
writeQueue = [NSOperationQueue new];
[writeQueue setMaxConcurrentOperationCount:1];
writeQueueLock = [NSRecursiveLock new];
RMLog(@"Opening database at %@", path);
db = [[FMDatabase alloc] initWithPath:path];
if (![db open])
{
RMLog(@"Could not connect to database - %@", [db lastErrorMessage]);
[[NSFileManager defaultManager] removeItemAtPath:path error:NULL];
dao = [[RMTileCacheDAO alloc] initWithDatabase:path];
}
if (![db open]) {
[self release];
return nil;
}
}
if (dao == nil)
return nil;
[db setCrashOnErrors:TRUE];
[db setShouldCacheStatements:TRUE];
[self configureDBForFirstUse];
tileCount = [self countTiles];
return self;
}
... ... @@ -88,7 +126,11 @@
- (void)dealloc
{
self.databasePath = nil;
[dao release]; dao = nil;
[writeQueueLock lock];
[writeQueue release]; writeQueue = nil;
[writeQueueLock unlock];
[writeQueueLock release]; writeQueueLock = nil;
[db close]; [db release]; db = nil;
[super dealloc];
}
... ... @@ -111,44 +153,142 @@
{
// RMLog(@"DB cache check for tile %d %d %d", tile.x, tile.y, tile.zoom);
NSData *data = [dao dataForTile:RMTileKey(tile) withKey:aCacheKey];
if (data == nil)
return nil;
[writeQueueLock lock];
FMResultSet *results = [db executeQuery:@"SELECT data FROM ZCACHE WHERE tile_hash = ? AND cache_key = ?", [RMTileCache tileHash:tile], aCacheKey];
if ([db hadError]) {
RMLog(@"DB error while fetching tile data: %@", [db lastErrorMessage]);
return nil;
}
NSData *data = nil;
UIImage *cachedImage = nil;
if ([results next]) {
data = [results dataForColumnIndex:0];
if (data) cachedImage = [UIImage imageWithData:data];
}
[results close];
[writeQueueLock unlock];
if (capacity != 0 && purgeStrategy == RMCachePurgeStrategyLRU) {
[dao touchTile:RMTileKey(tile) withKey:aCacheKey];
[self touchTile:tile withKey:aCacheKey];
}
// RMLog(@"DB cache hit tile %d %d %d (%@)", tile.x, tile.y, tile.zoom, [RMTileCache tileHash:tile]);
return [UIImage imageWithData:data];
return cachedImage;
}
- (void)addImage:(UIImage *)image forTile:(RMTile)tile withCacheKey:(NSString *)aCacheKey
{
// TODO: Converting the image here (again) is not so good...
NSData *data = UIImagePNGRepresentation(image);
if (capacity != 0) {
NSUInteger tilesInDb = [dao count];
if (capacity != 0)
{
NSUInteger tilesInDb = [self count];
if (capacity <= tilesInDb) {
[dao purgeTiles: MAX(minimalPurge, 1+tilesInDb-capacity)];
[self purgeTiles: MAX(minimalPurge, 1+tilesInDb-capacity)];
}
// RMLog(@"DB cache insert tile %d %d %d (%@)", tile.x, tile.y, tile.zoom, [RMTileCache tileHash:tile]);
[dao addData:data forTile:RMTileKey(tile) withKey:aCacheKey];
// Don't add new images to the database while there are still more than kWriteQueueLimit
// insert operations pending. This prevents some memory issues.
if ([writeQueue operationCount] > kWriteQueueLimit) return;
[writeQueue addOperationWithBlock:^{
// RMLog(@"addData\t%d", tileHash);
[writeQueueLock lock];
BOOL result = [db executeUpdate:@"INSERT OR IGNORE INTO ZCACHE (tile_hash, cache_key, last_used, data) VALUES (?, ?, ?, ?)", [RMTileCache tileHash:tile], aCacheKey, [NSDate date], data];
[writeQueueLock unlock];
if (result == NO)
{
RMLog(@"Error occured adding data");
} else
tileCount++;
}];
}
}
- (void)didReceiveMemoryWarning
#pragma mark -
- (NSUInteger)count
{
return tileCount;
}
- (NSUInteger)countTiles
{
[writeQueueLock lock];
NSUInteger count = 0;
FMResultSet *results = [db executeQuery:@"SELECT COUNT(tile_hash) FROM ZCACHE"];
if ([results next])
count = [results intForColumnIndex:0];
else
RMLog(@"Unable to count columns");
[results close];
[writeQueueLock unlock];
return count;
}
- (void)purgeTiles:(NSUInteger)count
{
[dao didReceiveMemoryWarning];
RMLog(@"purging %u old tiles from db cache", count);
[writeQueueLock lock];
BOOL result = [db executeUpdate: @"DELETE FROM ZCACHE WHERE tile_hash IN (SELECT tile_hash FROM ZCACHE ORDER BY last_used LIMIT ?)", [NSNumber numberWithUnsignedInt:count]];
[db executeQuery:@"VACUUM"];
tileCount = [self countTiles];
[writeQueueLock unlock];
if (result == NO) {
RMLog(@"Error purging cache");
}
}
- (void)removeAllCachedImages
{
[dao removeAllCachedImages];
[writeQueue addOperationWithBlock:^{
[writeQueueLock lock];
BOOL result = [db executeUpdate: @"DELETE FROM ZCACHE"];
[db executeQuery:@"VACUUM"];
[writeQueueLock unlock];
if (result == NO) {
RMLog(@"Error purging cache");
}
tileCount = [self countTiles];
}];
}
- (void)touchTile:(RMTile)tile withKey:(NSString *)cacheKey
{
[writeQueue addOperationWithBlock:^{
[writeQueueLock lock];
BOOL result = [db executeUpdate: @"UPDATE ZCACHE SET last_used = ? WHERE tile_hash = ? AND cache_key = ?", [NSDate date], [RMTileCache tileHash:tile], cacheKey];
[writeQueueLock unlock];
if (result == NO) {
RMLog(@"Error touching tile");
}
}];
}
- (void)didReceiveMemoryWarning
{
RMLog(@"Low memory in the tilecache");
[writeQueue cancelAllOperations];
}
@end
... ...
... ... @@ -7,6 +7,8 @@
*
*/
#import <CoreLocation/CoreLocation.h>
#ifndef _GLOBAL_CONSTANTS_H_
#define _GLOBAL_CONSTANTS_H_
... ...
... ... @@ -34,6 +34,7 @@
#import "RMProjection.h"
#import "RMMercatorToScreenProjection.h"
#import "RMMercatorToTileProjection.h"
#import "RMOpenStreetMapSource.h"
#import "RMTileCache.h"
#import "RMTileSource.h"
... ... @@ -83,7 +84,7 @@
here.longitude = kDefaultInitialLongitude;
return [self initWithView:view
tilesource:nil
tilesource:[[[RMOpenStreetMapSource alloc] init] autorelease]
centerLatLon:here
zoomLevel:kDefaultInitialZoomLevel
maxZoomLevel:kDefaultMaximumZoomLevel
... ...
... ... @@ -60,13 +60,15 @@
for (id cfg in cacheCfg)
{
id <RMTileCache> newCache = nil;
@try {
NSString *type = [cfg valueForKey:@"type"];
if ([@"memory-cache" isEqualToString:type])
if ([@"memory-cache" isEqualToString:type]) {
memoryCache = [[self memoryCacheWithConfig:cfg] retain];
continue;
}
if ([@"db-cache" isEqualToString:type])
newCache = [self databaseCacheWithConfig:cfg];
... ... @@ -186,7 +188,7 @@
NSUInteger capacity = 1000;
NSUInteger minimalPurge = capacity / 10;
NSNumber *capacityNumber = [cfg objectForKey:@"capacity"];
if (capacityNumber != nil) {
NSInteger value = [capacityNumber intValue];
... ... @@ -198,13 +200,13 @@
} else
RMLog(@"illegal value for capacity: %d", value);
}
NSString *strategyStr = [cfg objectForKey:@"strategy"];
if (strategyStr != nil) {
if ([strategyStr caseInsensitiveCompare:@"FIFO"] == NSOrderedSame) strategy = RMCachePurgeStrategyFIFO;
if ([strategyStr caseInsensitiveCompare:@"LRU"] == NSOrderedSame) strategy = RMCachePurgeStrategyLRU;
}
NSNumber *useCacheDirNumber = [cfg objectForKey:@"useCachesDirectory"];
if (useCacheDirNumber != nil)
useCacheDir = [useCacheDirNumber boolValue];
... ...
//
// DAO.h
//
// Copyright (c) 2008-2009, Route-Me Contributors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#import <UIKit/UIKit.h>
@class FMDatabase;
/// the interface between RMDatabaseCache and FMDB
@interface RMTileCacheDAO : NSObject {
FMDatabase* db;
NSUInteger tileCount;
NSOperationQueue *writeQueue;
NSRecursiveLock *writeQueueLock;
}
- (id)initWithDatabase:(NSString *)path;
- (NSUInteger)count;
- (NSData *)dataForTile:(uint64_t)tileHash withKey:(NSString *)cacheKey;
- (void)touchTile:(uint64_t)tileHash withKey:(NSString *)cacheKey;
- (void)addData:(NSData *)data forTile:(uint64_t)tileHash withKey:(NSString *)cacheKey;
- (void)purgeTiles:(NSUInteger)count;
- (void)removeAllCachedImages;
- (void)didReceiveMemoryWarning;
@end
//
// DAO.m
//
// Copyright (c) 2008-2009, Route-Me Contributors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#import "RMTileCacheDAO.h"
#import "FMDatabase.h"
#import "RMTileCache.h"
#import "RMTileImage.h"
#define kWriteQueueLimit 25
@interface RMTileCacheDAO ()
- (NSUInteger)countTiles;
@end
@implementation RMTileCacheDAO
- (void)configureDBForFirstUse
{
[db executeQuery:@"PRAGMA synchronous=OFF"];
[db executeQuery:@"PRAGMA journal_mode=OFF"];
[db executeUpdate:@"CREATE TABLE IF NOT EXISTS ZCACHE (tile_hash INTEGER NOT NULL, cache_key VARCHAR(25) NOT NULL, last_used DOUBLE NOT NULL, data BLOB NOT NULL)"];
[db executeUpdate:@"CREATE UNIQUE INDEX IF NOT EXISTS main_index ON ZCACHE(tile_hash, cache_key)"];
[db executeUpdate:@"CREATE INDEX IF NOT EXISTS last_used_index ON ZCACHE(last_used)"];
}
- (id)initWithDatabase:(NSString *)path
{
if (!(self = [super init]))
return nil;
writeQueue = [NSOperationQueue new];
[writeQueue setMaxConcurrentOperationCount:1];
writeQueueLock = [NSRecursiveLock new];
RMLog(@"Opening database at %@", path);
db = [[FMDatabase alloc] initWithPath:path];
if (![db open])
{
RMLog(@"Could not connect to database - %@", [db lastErrorMessage]);
return nil;
}
[db setCrashOnErrors:TRUE];
[db setShouldCacheStatements:TRUE];
[self configureDBForFirstUse];
tileCount = [self countTiles];
return self;
}
- (void)dealloc
{
LogMethod();
[writeQueueLock lock];
[writeQueue release]; writeQueue = nil;
[writeQueueLock unlock];
[writeQueueLock release]; writeQueueLock = nil;
[db close]; [db release]; db = nil;
[super dealloc];
}
- (NSUInteger)count
{
return tileCount;
}
- (NSUInteger)countTiles
{
[writeQueueLock lock];
NSUInteger count = 0;
FMResultSet *results = [db executeQuery:@"SELECT COUNT(tile_hash) FROM ZCACHE"];
if ([results next])
count = [results intForColumnIndex:0];
else
RMLog(@"Unable to count columns");
[results close];
[writeQueueLock unlock];
return count;
}
- (NSData *)dataForTile:(uint64_t)tileHash withKey:(NSString *)cacheKey
{
[writeQueueLock lock];
FMResultSet *results = [db executeQuery:@"SELECT data FROM ZCACHE WHERE tile_hash = ? AND cache_key = ?", [NSNumber numberWithUnsignedLongLong:tileHash], cacheKey];
if ([db hadError]) {
RMLog(@"DB error while fetching tile data: %@", [db lastErrorMessage]);
return nil;
}
NSData *data = nil;
if ([results next])
// TODO: Would dataNoCopy work? What would we have to do?
data = [results dataForColumnIndex:0];
[results close];
[writeQueueLock unlock];
return data;
}
- (void)purgeTiles:(NSUInteger)count
{
RMLog(@"purging %u old tiles from db cache", count);
[writeQueueLock lock];
BOOL result = [db executeUpdate: @"DELETE FROM ZCACHE WHERE tile_hash IN (SELECT tile_hash FROM ZCACHE ORDER BY last_used LIMIT ?)", [NSNumber numberWithUnsignedInt:count]];
[db executeQuery:@"VACUUM"];
tileCount = [self countTiles];
[writeQueueLock unlock];
if (result == NO) {
RMLog(@"Error purging cache");
}
}
- (void)removeAllCachedImages
{
[writeQueue addOperationWithBlock:^{
[writeQueueLock lock];
BOOL result = [db executeUpdate: @"DELETE FROM ZCACHE"];
[db executeQuery:@"VACUUM"];
[writeQueueLock unlock];
if (result == NO) {
RMLog(@"Error purging cache");
}
tileCount = [self countTiles];
}];
}
- (void)touchTile:(uint64_t)tileHash withKey:(NSString *)cacheKey
{
[writeQueue addOperationWithBlock:^{
[writeQueueLock lock];
BOOL result = [db executeUpdate: @"UPDATE ZCACHE SET last_used = ? WHERE tile_hash = ? AND cache_key = ?", [NSDate date], [NSNumber numberWithUnsignedInt:tileHash], cacheKey];
[writeQueueLock unlock];
if (result == NO) {
RMLog(@"Error touching tile");
}
}];
}
- (void)addData:(NSData *)data forTile:(uint64_t)tileHash withKey:(NSString *)cacheKey
{
// Don't add new images to the database while there are still more than kWriteQueueLimit
// insert operations pending. This prevents some memory issues.
if ([writeQueue operationCount] > kWriteQueueLimit) return;
[writeQueue addOperationWithBlock:^{
// RMLog(@"addData\t%d", tileHash);
[writeQueueLock lock];
BOOL result = [db executeUpdate:@"INSERT OR IGNORE INTO ZCACHE (tile_hash, cache_key, last_used, data) VALUES (?, ?, ?, ?)", [NSNumber numberWithUnsignedLongLong:tileHash], cacheKey, [NSDate date], data];
[writeQueueLock unlock];
if (result == NO)
{
RMLog(@"Error occured adding data");
} else
tileCount++;
}];
}
- (void)didReceiveMemoryWarning
{
RMLog(@"Low memory in the tilecache");
[writeQueue cancelAllOperations];
}
@end
... ... @@ -130,7 +130,7 @@ static UIImage *_missingTile = nil;
- (void)updateWithImage:(UIImage *)image andNotify:(BOOL)notifyListeners
{
dispatch_async(dispatch_get_main_queue(),^ {
dispatch_async(dispatch_get_main_queue(), ^{
layer.contents = (id)[image CGImage];
});
... ...
... ... @@ -82,7 +82,6 @@
2BEC60490F8AC738008FB858 /* RMProjection.m in Sources */ = {isa = PBXBuildFile; fileRef = B83E64E40E80E73F001663B6 /* RMProjection.m */; };
2BEC604A0F8AC739008FB858 /* RMTile.c in Sources */ = {isa = PBXBuildFile; fileRef = B83E64D70E80E73F001663B6 /* RMTile.c */; };
2BEC604B0F8AC73A008FB858 /* RMTileCache.m in Sources */ = {isa = PBXBuildFile; fileRef = B83E64D10E80E73F001663B6 /* RMTileCache.m */; };
2BEC604C0F8AC73C008FB858 /* RMTileCacheDAO.m in Sources */ = {isa = PBXBuildFile; fileRef = B8474B970EB40094006A0BC1 /* RMTileCacheDAO.m */; };
2BEC604E0F8AC73D008FB858 /* RMTileImage.m in Sources */ = {isa = PBXBuildFile; fileRef = B83E64D90E80E73F001663B6 /* RMTileImage.m */; };
2BEC604F0F8AC73E008FB858 /* RMTileImageSet.m in Sources */ = {isa = PBXBuildFile; fileRef = B83E64E10E80E73F001663B6 /* RMTileImageSet.m */; };
2BEC60500F8AC73F008FB858 /* RMTileLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = B83E64C70E80E73F001663B6 /* RMTileLoader.m */; };
... ... @@ -105,8 +104,6 @@
B8474B9D0EB40094006A0BC1 /* FMDatabaseAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = B8474B900EB40094006A0BC1 /* FMDatabaseAdditions.m */; };
B8474B9F0EB40094006A0BC1 /* FMResultSet.h in Headers */ = {isa = PBXBuildFile; fileRef = B8474B920EB40094006A0BC1 /* FMResultSet.h */; };
B8474BA00EB40094006A0BC1 /* FMResultSet.m in Sources */ = {isa = PBXBuildFile; fileRef = B8474B930EB40094006A0BC1 /* FMResultSet.m */; };
B8474BA20EB40094006A0BC1 /* RMTileCacheDAO.h in Headers */ = {isa = PBXBuildFile; fileRef = B8474B960EB40094006A0BC1 /* RMTileCacheDAO.h */; };
B8474BA30EB40094006A0BC1 /* RMTileCacheDAO.m in Sources */ = {isa = PBXBuildFile; fileRef = B8474B970EB40094006A0BC1 /* RMTileCacheDAO.m */; };
B8474BA40EB40094006A0BC1 /* RMDatabaseCache.h in Headers */ = {isa = PBXBuildFile; fileRef = B8474B980EB40094006A0BC1 /* RMDatabaseCache.h */; };
B8474BA50EB40094006A0BC1 /* RMDatabaseCache.m in Sources */ = {isa = PBXBuildFile; fileRef = B8474B990EB40094006A0BC1 /* RMDatabaseCache.m */; };
B8474BC10EB4019A006A0BC1 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B8474BC00EB4019A006A0BC1 /* libsqlite3.dylib */; };
... ... @@ -281,8 +278,6 @@
B8474B910EB40094006A0BC1 /* fmdb.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = fmdb.m; sourceTree = "<group>"; };
B8474B920EB40094006A0BC1 /* FMResultSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMResultSet.h; sourceTree = "<group>"; };
B8474B930EB40094006A0BC1 /* FMResultSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMResultSet.m; sourceTree = "<group>"; };
B8474B960EB40094006A0BC1 /* RMTileCacheDAO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMTileCacheDAO.h; sourceTree = "<group>"; };
B8474B970EB40094006A0BC1 /* RMTileCacheDAO.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMTileCacheDAO.m; sourceTree = "<group>"; };
B8474B980EB40094006A0BC1 /* RMDatabaseCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RMDatabaseCache.h; sourceTree = "<group>"; };
B8474B990EB40094006A0BC1 /* RMDatabaseCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RMDatabaseCache.m; sourceTree = "<group>"; };
B8474BC00EB4019A006A0BC1 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; };
... ... @@ -531,7 +526,6 @@
B83E64D30E80E73F001663B6 /* RMMemoryCache.m */,
B8474B980EB40094006A0BC1 /* RMDatabaseCache.h */,
B8474B990EB40094006A0BC1 /* RMDatabaseCache.m */,
B8474B940EB40094006A0BC1 /* Database */,
);
name = "Tile Cache";
sourceTree = "<group>";
... ... @@ -587,16 +581,6 @@
path = FMDB;
sourceTree = "<group>";
};
B8474B940EB40094006A0BC1 /* Database */ = {
isa = PBXGroup;
children = (
B8474B8C0EB40094006A0BC1 /* FMDB */,
B8474B960EB40094006A0BC1 /* RMTileCacheDAO.h */,
B8474B970EB40094006A0BC1 /* RMTileCacheDAO.m */,
);
name = Database;
sourceTree = "<group>";
};
B8474C610EB53A01006A0BC1 /* Resources */ = {
isa = PBXGroup;
children = (
... ... @@ -633,6 +617,7 @@
isa = PBXGroup;
children = (
175701DB1323C2CF00A5D314 /* iOS Additions */,
B8474B8C0EB40094006A0BC1 /* FMDB */,
17F02BB01319BA4B00260C6B /* RouteMe.h */,
B1EB26C510B5D8E6009F8658 /* RMNotifications.h */,
96492C3F0FA8AD3400EBA6D2 /* RMGlobalConstants.h */,
... ... @@ -706,7 +691,6 @@
B8474B9A0EB40094006A0BC1 /* FMDatabase.h in Headers */,
B8474B9C0EB40094006A0BC1 /* FMDatabaseAdditions.h in Headers */,
B8474B9F0EB40094006A0BC1 /* FMResultSet.h in Headers */,
B8474BA20EB40094006A0BC1 /* RMTileCacheDAO.h in Headers */,
B8474BA40EB40094006A0BC1 /* RMDatabaseCache.h in Headers */,
23A0AAEB0EB90AA6003A4521 /* RMFoundation.h in Headers */,
B8800FF10EC3A237003E9CDD /* RMMarkerManager.h in Headers */,
... ... @@ -892,7 +876,6 @@
2BEC60490F8AC738008FB858 /* RMProjection.m in Sources */,
2BEC604A0F8AC739008FB858 /* RMTile.c in Sources */,
2BEC604B0F8AC73A008FB858 /* RMTileCache.m in Sources */,
2BEC604C0F8AC73C008FB858 /* RMTileCacheDAO.m in Sources */,
2BEC604E0F8AC73D008FB858 /* RMTileImage.m in Sources */,
2BEC604F0F8AC73E008FB858 /* RMTileImageSet.m in Sources */,
2BEC60500F8AC73F008FB858 /* RMTileLoader.m in Sources */,
... ... @@ -935,7 +918,6 @@
B8474B9B0EB40094006A0BC1 /* FMDatabase.m in Sources */,
B8474B9D0EB40094006A0BC1 /* FMDatabaseAdditions.m in Sources */,
B8474BA00EB40094006A0BC1 /* FMResultSet.m in Sources */,
B8474BA30EB40094006A0BC1 /* RMTileCacheDAO.m in Sources */,
B8474BA50EB40094006A0BC1 /* RMDatabaseCache.m in Sources */,
126693040EB76C0B00E002D5 /* RMConfiguration.m in Sources */,
23A0AAE90EB90A99003A4521 /* RMFoundation.c in Sources */,
... ...
... ... @@ -236,6 +236,7 @@
isa = PBXProject;
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MarkerMurder" */;
compatibilityVersion = "Xcode 3.1";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
... ...
... ... @@ -39,8 +39,7 @@
CLLocationCoordinate2D firstLocation;
firstLocation.latitude = 51.2795;
firstLocation.longitude = 1.082;
self.mapView = [[[RMMapView alloc] initWithFrame:CGRectMake(10,20,200,300)
WithLocation:firstLocation] autorelease];
self.mapView = [[[RMMapView alloc] initWithFrame:CGRectMake(10,20,200,300)] autorelease];
// [[mapView contents] setZoom:10.0];
[mapView setBackgroundColor:[UIColor greenColor]];
[[self view] addSubview:mapView];
... ...
... ... @@ -184,7 +184,14 @@
isa = PBXProject;
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ProgrammaticMap" */;
compatibilityVersion = "Xcode 3.1";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
Japanese,
French,
German,
);
mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
projectDirPath = "";
projectReferences = (
... ...
... ... @@ -8,7 +8,7 @@
#import "MainView.h"
#import "RMCloudMadeMapSource.h"
#import "RMOpenStreetMapSource.h"
@implementation MainViewController
... ... @@ -27,12 +27,7 @@
- (void)viewDidLoad {
[super viewDidLoad];
[mapView setDelegate:self];
id myTilesource = [[[RMCloudMadeMapSource alloc] initWithAccessKey:@"0199bdee456e59ce950b0156029d6934" styleNumber:999] autorelease];
// have to initialize the RMMapContents object explicitly if we want it to use a particular tilesource
[[[RMMapContents alloc] initWithView:mapView
tilesource:myTilesource] autorelease];
/* -- Uncomment to constrain view
[mapView setConstraintsSW:((CLLocationCoordinate2D){-33.942221,150.996094})
NE:((CLLocationCoordinate2D){-33.771157,151.32019})]; */
... ...
... ... @@ -19,7 +19,7 @@
[window makeKeyAndVisible];
}
-(RMMapContents *)mapContents
- (RMMapContents *)mapContents
{
return self.rootViewController.mainViewController.mapView.contents;
}
... ...
... ... @@ -79,7 +79,7 @@
anchorPoint:CGPointMake(0.5, 1.0)];
[marker changeLabelUsingText:@"Hello"];
[markerManager addMarker:marker AtLatLong:[[mapView contents] mapCenter]];
[markerManager addMarker:marker atLatLong:[[mapView contents] mapCenter]];
[marker release];
markers = [markerManager markersWithinScreenBounds];
... ... @@ -111,7 +111,7 @@
NSLog(@"New location: east:%lf north:%lf", [marker projectedLocation].easting, [marker projectedLocation].northing);
CGRect rect = [marker bounds];
[markerManager moveMarker:marker AtXY:CGPointMake(position.x,position.y +rect.size.height/3)];
[markerManager moveMarker:marker atXY:CGPointMake(position.x,position.y +rect.size.height/3)];
}
... ... @@ -129,14 +129,14 @@
[marker replaceUIImage:[UIImage imageNamed:@"marker-red.png"]];
[marker changeLabelUsingText:@"World"];
tap=YES;
[markerManager moveMarker:marker AtXY:CGPointMake([marker position].x,[marker position].y + 20.0)];
[markerManager moveMarker:marker atXY:CGPointMake([marker position].x,[marker position].y + 20.0)];
[mapView setDeceleration:YES];
}else
{
[marker replaceUIImage:[UIImage imageNamed:@"marker-blue.png"]
anchorPoint:CGPointMake(0.5, 1.0)];
[marker changeLabelUsingText:@"Hello"];
[markerManager moveMarker:marker AtXY:CGPointMake([marker position].x,[marker position].y - 20.0)];
[markerManager moveMarker:marker atXY:CGPointMake([marker position].x,[marker position].y - 20.0)];
tap=NO;
[mapView setDeceleration:NO];
}
... ... @@ -165,7 +165,7 @@
anchorPoint:CGPointMake(0.5, 1.0)];
[marker setTextForegroundColor:[UIColor blueColor]];
[marker changeLabelUsingText:@"Hello"];
[markerManager addMarker:marker AtLatLong:[[mapView contents] mapCenter]];
[markerManager addMarker:marker atLatLong:[[mapView contents] mapCenter]];
[marker release];
NSLog(@"Center: Lat: %lf Lon: %lf", mapView.contents.mapCenter.latitude, mapView.contents.mapCenter.longitude);
}
... ...
... ... @@ -202,6 +202,7 @@
isa = PBXProject;
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "SimpleMap" */;
compatibilityVersion = "Xcode 3.1";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
... ...
... ... @@ -74,7 +74,7 @@
[marker changeLabelUsingText:@"Hello"];
[markerManager addMarker:marker
AtLatLong:[[mapView contents] mapCenter]];
atLatLong:[[mapView contents] mapCenter]];
[marker release];
markers = [markerManager markersWithinScreenBounds];
... ... @@ -111,7 +111,7 @@ shouldDragMarker:(RMMarker *)marker
CGRect rect = [marker bounds];
[markerManager moveMarker:marker
AtXY:CGPointMake(position.x,position.y +rect.size.height/3)];
atXY:CGPointMake(position.x,position.y +rect.size.height/3)];
}
... ... @@ -133,7 +133,7 @@ shouldDragMarker:(RMMarker *)marker
[marker changeLabelUsingText:@"World"];
tap=YES;
[markerManager moveMarker:marker
AtXY:CGPointMake([marker position].x,[marker position].y + 20.0)];
atXY:CGPointMake([marker position].x,[marker position].y + 20.0)];
[mapView setDeceleration:YES];
}
else
... ... @@ -142,7 +142,7 @@ shouldDragMarker:(RMMarker *)marker
anchorPoint:CGPointMake(0.5, 1.0)];
[marker changeLabelUsingText:@"Hello"];
[markerManager moveMarker:marker
AtXY:CGPointMake([marker position].x, [marker position].y - 20.0)];
atXY:CGPointMake([marker position].x, [marker position].y - 20.0)];
tap = NO;
[mapView setDeceleration:NO];
}
... ... @@ -195,7 +195,7 @@ shouldDragMarker:(RMMarker *)marker
[marker setTextForegroundColor:[UIColor blueColor]];
[marker changeLabelUsingText:@"Hello"];
[markerManager addMarker:marker
AtLatLong:currentLocation];
atLatLong:currentLocation];
[marker release];
}
... ... @@ -245,7 +245,7 @@ shouldDragMarker:(RMMarker *)marker
location.longitude == oldLocation.coordinate.longitude)
{
[markerManager moveMarker: marker
AtLatLon: newLocation.coordinate];
atLatLon: newLocation.coordinate];
break; // We're done.
}
}
... ...
... ... @@ -201,7 +201,14 @@
isa = PBXProject;
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "SimpleSampleMap" */;
compatibilityVersion = "Xcode 3.1";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
Japanese,
French,
German,
);
mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
projectDirPath = "";
projectReferences = (
... ...
... ... @@ -23,7 +23,7 @@
latlong.latitude = 43.61675;
latlong.longitude = 6.97167;
RMMapView *map = [[RMMapView alloc]initWithFrame:CGRectMake(0.0, 0.0, [[UIScreen mainScreen]applicationFrame].size.width, [[UIScreen mainScreen]applicationFrame].size.height-79) WithLocation:latlong];
RMMapView *map = [[RMMapView alloc]initWithFrame:CGRectMake(0.0, 0.0, [[UIScreen mainScreen]applicationFrame].size.width, [[UIScreen mainScreen]applicationFrame].size.height-79)];
[self setMapView:map];
[map release];
[[[self mapView] contents]setZoom:18];
... ...