快问你的问题。我有一个我正在研究的应用程序需要使用地图,但不会有网络连接。我见过其他人就此问过类似的问题,但我的要求略有不同,所以我想发一个新问题。
以下是我对该应用的要求。
- 允许使用可定义的注释捏合/缩放地图
- 地图必须离线可用
- 地图应限制在某个地理区域
- 应用程序不必通过Apple检查。这是一个企业应用程序,将作为自助服务终端。
那么,是否存在任何人都可以建议的缓存地图图块的框架或方法?
谢谢你提前出去。
快问你的问题。我有一个我正在研究的应用程序需要使用地图,但不会有网络连接。我见过其他人就此问过类似的问题,但我的要求略有不同,所以我想发一个新问题。
以下是我对该应用的要求。
那么,是否存在任何人都可以建议的缓存地图图块的框架或方法?
谢谢你提前出去。
我使用MapKit的默认地图和MKTileOverlay的子类来保存下载的图块并返回已经缓存的图块而不下载它们。
1)从MapKit更改默认地图的来源并使用MKTileOverlay的子类(此处使用“打开街道地图”)
- (void)viewDidLoad{
[super viewDidLoad];
static NSString * const template = @"http://tile.openstreetmap.org/{z}/{x}/{y}.png";
VHTileOverlay *overlay = [[VHTileOverlay alloc] initWithURLTemplate:template];
overlay.canReplaceMapContent = YES;
[self.mapView addOverlay:overlay level:MKOverlayLevelAboveLabels];
}
2)来自MKTileOverlay的子类
@interface VHTileOverlay() // MKTileOverlay subclass
@property (nonatomic, strong) NSOperationQueue *operationQueue;
@end
@implementation VHTileOverlay
-(instancetype)initWithURLTemplate:(NSString *)URLTemplate{
self = [super initWithURLTemplate:URLTemplate];
if(self){
self.directoryPath = cachePath;
self.operationQueue = [NSOperationQueue new];
}
return self;
}
-(NSURL *)URLForTilePath:(MKTileOverlayPath)path {
return [NSURL URLWithString:[NSString stringWithFormat:@"http://tile.openstreetmap.org/%ld/%ld/%ld.png", (long)path.z, (long)path.x, (long)path.y]];
}
-(void)loadTileAtPath:(MKTileOverlayPath)path
result:(void (^)(NSData *data, NSError *error))result
{
if (!result) {
return;
}
NSString *pathToFilfe = [[self URLForTilePath:path] absoluteString];
pathToFilfe = [pathToFilfe stringByReplacingOccurrencesOfString:@"/" withString:@"|"];
// @"/" - those are not approriate for file's url...
NSData *cachedData = [self loadFileWithName:pathToFilfe];
if (cachedData) {
result(cachedData, nil);
} else {
NSURLRequest *request = [NSURLRequest requestWithURL:[self URLForTilePath:path]];
__block VHTileOverlay *weakSelf = self;
[NSURLConnection sendAsynchronousRequest:request
queue:self.operationQueue
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSLog(@"%@",[weakSelf URLForTilePath:path]);
if(data){
[self saveFileWithName:[[weakSelf URLForTilePath:path] absoluteString] imageData:data];
}
result(data, connectionError);
}];
}
}
-(NSString *)pathToImageWithName:(NSString *)fileName
{
NSString *imageFilePath = [[OfflineMapCache sharedObject].cachePath stringByAppendingPathComponent:fileName];
return imageFilePath;
}
- (NSData *)loadFileWithName:(NSString *)fileName
{
NSString *imagePath = [self pathToImageWithName:fileName];
NSData *data = [[NSData alloc] initWithContentsOfFile:imagePath];
return data;
}
- (void)saveFileWithName:(NSString *)fileName imageData:(NSData *)imageData
{
// fileName = [fileName stringByReplacingOccurrencesOfString:@"/" withString:@"|"];
// NSString *imagePath = [self pathToImageWithName:fileName];
// [imageData writeToFile:imagePath atomically:YES];
}
取消注释“saveFileWithName”并在模拟器上运行它。您还可以添加NSLog(fileName)以了解获取所需的所有切片的位置。 (模拟器缓存位于Users / YOU / Library / Developer / CoreSimulator / Devices / ...而Library是一个隐藏目录)
缓存完所有内容后,只需输入应用程序包(就像任何其他图像一样,如果你想从盒子缓存的地图中获取)。并告诉你
- (void)loadTileAtPath:(MKTileOverlayPath)path
result:(void (^)(NSData *data, NSError *error))result
从捆绑中获取图块。
所以现在我可以安装我的应用程序,关闭wi-fi,无论如何我都会得到这些地图。
尝试使用 http://mapbox.com/ 它有iOS SDK和用于构建离线地图的应用程序。
检查第10.3节 Google地图服务条款 并且您会发现您不能存储任何Google地图内容。这意味着您不仅需要提供自己的地图,还需要替换方便的MapKit功能。据我所知,你根本无法使用MapKit进行离线应用。
不幸的是,MapKit Framework不支持离线地图访问。你应该更喜欢MapBox iOS SDK(MapBox iOS SDK是一个用于构建地图应用程序的工具集,支持离线缓存策略,缩放限制,视网膜显示行为,起始坐标和拖动减速的地图视图等....
快乐的编码
见 skobbler / Telenav SDK - 它基于OpenStreetMap,是mapkit(地图渲染,路由和转弯导航)的一个(几乎)完全堆栈替代品,具有对离线地图的集成支持