Open Street Maps などの選択したサービスからオフラインで使用するために、マップ タイルを表示し、キャッシュしたいと考えています。これは簡単なようで、iOS7
次を使用して機能します。
static NSString * const template = @"http://tile.openstreetmap.org/{z}/{x}/{y}.png";
self.tileOverlay = [[ZSSTileOverlay alloc] initWithURLTemplate:template];
self.tileOverlay.canReplaceMapContent = YES;
[self.mapView addOverlay:self.tileOverlay level:MKOverlayLevelAboveLabels];
私のMKTileOverLay
サブクラスではloadTileAtPath:result:
、タイルをダウンロードしてオフラインで使用するためにディスクに保存するようにオーバーライドしています。後で、ユーザーがマップのどの部分をダウンロードするかを選択する方法を実装します。
- (void)loadTileAtPath:(MKTileOverlayPath)path result:(void (^)(NSData *tileData, NSError *error))result {
NSString *url = [NSString stringWithFormat:@"http://tile.openstreetmap.org/%li/%li/%li.png", (long)path.z, (long)path.x, (long)path.y];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (data == nil) {
// Load a default tile here
} else {
UIImage *image = [[UIImage alloc] initWithData:data];
result(data, nil);
NSString *pathForWritting = [self pathToWriteImage:path];
NSString *fileName = [NSString stringWithFormat:@"%li", (long)path.y];
[self saveImage:image withFileName:fileName ofType:@"png" inDirectory:pathForWritting];
}
}];
}
- (void)saveImage:(UIImage *)image withFileName:(NSString *)imageName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath {
// Create folder structure if it doesn't exist
if (![[NSFileManager defaultManager] fileExistsAtPath:directoryPath]) {
NSError *error = nil;
[[NSFileManager defaultManager] createDirectoryAtPath:directoryPath withIntermediateDirectories:YES attributes:nil error:&error];
if (error) {
NSLog(@"ERROR: %@", error.localizedDescription);
}
}
if ([[extension lowercaseString] isEqualToString:@"png"]) {
NSString *fullPath = [directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"png"]];
[UIImagePNGRepresentation(image) writeToFile:fullPath atomically:YES];
} else if ([[extension lowercaseString] isEqualToString:@"jpg"] || [[extension lowercaseString] isEqualToString:@"jpeg"]) {
[UIImageJPEGRepresentation(image, 1.0) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"jpg"]] options:NSAtomicWrite error:nil];
}
}
- (NSURL *)applicationDocumentsDirectory {
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask] lastObject];
}
- (NSString *)pathToWriteImage:(MKTileOverlayPath)path {
NSString *pathFolder = [NSString stringWithFormat:@"tiles/%li/%li", (long)path.z, (long)path.x];
return [NSString stringWithFormat:@"%@/%@", [self applicationDocumentsDirectory].path, pathFolder];
}
これはまさに私が期待したとおりに機能し、画像を適切な名前のフォルダーに保存します。
さて、ここでの本当の問題は 3 つあります。
- タイルをディスクに保存し、オフライン時にそれらをロードすることは良い考えですか? または、これらを SQL Lite DB などに保存する必要がありますか?
- タイルは によって自動的に読み込まれるようですが、
MapKit
でもう一度ダウンロードする必要があるのはなぜloadTitleAtPath:
ですか?MKMapView
既に読み込まれているタイルを取得する方法はありませんか? - ユーザーがダウンロードしたいマップの部分とマップレベルを選択できるようにするための良い方法は何ですか? すべてのズーム レベルが現在のものよりも高い現在の四角形?