Reputation: 7391
Hello i am using MKTileOverlay
to present OpenStreetMap tiles in my iOS7 App
. Now i'd like to implement the ability to cache these tiles. I saw a post on NSHipster (http://nshipster.com/mktileoverlay-mkmapsnapshotter-mkdirections/) and did it accordingly.
This is my MKTileOverlay subclass:
#import "DETileOverlay.h"
@implementation DETileOverlay
- (void)loadTileAtPath:(MKTileOverlayPath)path
result:(void (^)(NSData *data, NSError *error))result
{
if (!result)
{
return;
}
NSData *cachedData = [self.cache objectForKey:[self URLForTilePath:path]];
if (cachedData)
{
result(cachedData, nil);
}
else
{
NSURLRequest *request = [NSURLRequest requestWithURL:[self URLForTilePath:path]];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
result(data, connectionError);
}];
}
}
@end
Then i use it like this:
#import "DETileOverlay.h"
@interface DEMapViewController : UIViewController <MKMapViewDelegate> {
}
@property (nonatomic, retain) DETileOverlay *overlay;
-(void)viewDidLoad {
[super viewDidLoad];
self.overlay = [[DETileOverlay alloc] initWithURLTemplate:@"http://tile.stamen.com/watercolor/{z}/{x}/{y}.jpg"];
self.overlay.canReplaceMapContent = YES;
self.overlay.mapView = map;
[map addOverlay:self.overlay level:MKOverlayLevelAboveLabels];
}
// iOS 7
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOverlay>)ovl
{
MKTileOverlayRenderer *renderer = [[MKTileOverlayRenderer alloc]initWithOverlay:ovl];
return renderer;
}
- (void) mapView:(MKMapView *)mapView
didUpdateUserLocation:(MKUserLocation *)userLocation
{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.location.coordinate, 300, 300);
[map setRegion:region animated:YES];
}
When i start my app no tiles are loaded. If i don't override the loadTileAtPath in my subclass everything works fine. What am i doing wrong ?
Thanks so much.
Upvotes: 2
Views: 2807
Reputation: 446
I don't see it in your code, but be sure to initialize your cache and operation queue. Using your code exactly does not work. When I initialize the MKTileOverlay, I set its cache and operation queue. Then it all works.
Upvotes: 0
Reputation: 3963
Based on the comments you say you've solved it, but based on your code you never add the tiles to your cache. Without that I don't think you'll get any caching and will always be requesting the tiles anyway. So in your completionHandler you should be adding the resulting tile to your cache like this:
....
} else {
NSURLRequest *request = [NSURLRequest requestWithURL:[self URLForTilePath:path]];
[NSURLConnection sendAsynchronousRequest:request queue:self.operationQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// Should inspect the response to see if the request completed successfully!!
[self.cache setObject:data forKey:[self URLForTilePath:path]];
result(data, connectionError);
}];
}
Upvotes: 2