I want to display and also cache map fragments for offline use with a selected service such as Open Street Maps. This seems simple, as iOS7it works with:
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];
In my subclass, MKTileOverLayI override loadTileAtPath:result:to load tiles and save them to disk for offline use. Later I will implement a method for users to select which part of the map to load:
- (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) {
} 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 {
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];
}
This works exactly as I would expect, and it saves the images in the appropriate folders:

Now the real question is thrice here:
- Does the tile save to disk and then load it back offline? Or should they be stored in something like SQL Lite DB?
- ,
MapKit, loadTitleAtPath:? , MKMapView ? - (, , ), , ? ?