Skip to content

Instantly share code, notes, and snippets.

@respectTheCode
Created August 27, 2014 22:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save respectTheCode/421c329f3551321099d4 to your computer and use it in GitHub Desktop.
Save respectTheCode/421c329f3551321099d4 to your computer and use it in GitHub Desktop.
#import "APMapBoxLayer.h"
@implementation APMapBoxLayer {
MKMapView *_mapView;
MBXRasterTileOverlay *_rasterOverlay;
NSString *_mapId;
BOOL _usingOfflineMap;
BOOL _readyToDownload;
BOOL _didStartDownload;
NSUInteger _startingZoom;
MKCoordinateRegion _startingRegion;
}
- (id)initWithLayerData:(NSDictionary *)layerData {
if ((self = [super initWithLayerData:layerData])) {
_mapId = layerData[@"mid"];
_mapView = [[MKMapView alloc] init];
[self addSubview:_mapView];
_mapView.frame = self.bounds;
_mapView.delegate = self;
MBXOfflineMapDownloader *sharedDownloader = [MBXOfflineMapDownloader sharedOfflineMapDownloader];
sharedDownloader.delegate = self;
_rasterOverlay = [[MBXRasterTileOverlay alloc] initWithMapID:_mapId];
_rasterOverlay.delegate = self;
[_mapView addOverlay:_rasterOverlay];
if(sharedDownloader.state == MBXOfflineMapDownloaderStateSuspended) {
[[MBXOfflineMapDownloader sharedOfflineMapDownloader] resume];
}
}
return self;
}
- (MBXOfflineMapDatabase *)getOfflineDatabaseForMapId:(NSString *)mapId {
for(MBXOfflineMapDatabase *db in [MBXOfflineMapDownloader sharedOfflineMapDownloader].offlineMapDatabases) {
if ([db.mapID isEqualToString:mapId]) {
return db;
}
}
return nil;
}
- (void)downloadMap {
if (!_readyToDownload || _didStartDownload) return;
_didStartDownload = YES;
MBXOfflineMapDownloader *sharedDownloader = [MBXOfflineMapDownloader sharedOfflineMapDownloader];
if (sharedDownloader.state != MBXOfflineMapDownloaderStateAvailable) return;
if (_usingOfflineMap) return;
if ([self getOfflineDatabaseForMapId:_mapId]) return;
[sharedDownloader beginDownloadingMapID:_mapId mapRegion:_startingRegion minimumZ:_startingZoom maximumZ:_startingZoom];
}
- (void)showOfflineMap {
MBXOfflineMapDatabase *offlineMap = [self getOfflineDatabaseForMapId:_mapId];
if (offlineMap) {
_rasterOverlay = [[MBXRasterTileOverlay alloc] initWithOfflineMapDatabase:offlineMap];
_rasterOverlay.delegate = self;
_usingOfflineMap = YES;
_mapView.scrollEnabled = NO;
_mapView.zoomEnabled = NO;
_mapView.rotateEnabled = NO;
}
}
- (void)offlineMapDownloader:(MBXOfflineMapDownloader *)offlineMapDownloader stateChangedTo:(MBXOfflineMapDownloaderState)state {
[self downloadMap];
}
#ifdef IS_DEBUG
- (void)offlineMapDownloader:(MBXOfflineMapDownloader *)offlineMapDownloader totalFilesExpectedToWrite:(NSUInteger)totalFilesExpectedToWrite {
LOG(@"MAPBOX to download %lu files", (unsigned long)totalFilesExpectedToWrite);
}
- (void)offlineMapDownloader:(MBXOfflineMapDownloader *)offlineMapDownloader totalFilesWritten:(NSUInteger)totalFilesWritten totalFilesExpectedToWrite:(NSUInteger)totalFilesExpectedToWrite {
LOG(@"MAPBOX downloaded %lu of %lu files", (unsigned long)totalFilesWritten, (unsigned long)totalFilesExpectedToWrite);
}
- (void)offlineMapDownloader:(MBXOfflineMapDownloader *)offlineMapDownloader didEncounterRecoverableError:(NSError *)error {
if(error.code == MBXMapKitErrorCodeURLSessionConnectivity) {
LOG(@"The offline map download was suspended in response to a network connectivity error: %@",error);
} else if(error.code == MBXMapKitErrorCodeHTTPStatus) {
// The HTTP status response for one of the urls requested by the offline map came back as something other than 200. This is
// not necessarily bad, but it probably indicates a problem with the parameters used to begin an offline map download. For
// example, you might have requested markers for a map that doesn't have any.
//
LOG(@"The offline map downloader encountered an HTTP status error: %@",error);
} else if(error.code == MBXMapKitErrorCodeOfflineMapSqlite) {
// There was an sqlite error with the offline map. The most likely explanation is that the disk is running out of space.
//
LOG(@"The offline map downloader encountered an sqlite error: %@",error);
}
}
#endif
#pragma mark - MKMapViewDelegate protocol implementation
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
// This is boilerplate code to connect tile overlay layers with suitable renderers
//
if ([overlay isKindOfClass:[MBXRasterTileOverlay class]]) {
MKTileOverlayRenderer *renderer = [[MKTileOverlayRenderer alloc] initWithTileOverlay:overlay];
return renderer;
}
return nil;
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
// This is boilerplate code to connect annotations with suitable views
if ([annotation isKindOfClass:[MBXPointAnnotation class]]) {
static NSString *MBXSimpleStyleReuseIdentifier = @"MBXSimpleStyleReuseIdentifier";
MKAnnotationView *view = [mapView dequeueReusableAnnotationViewWithIdentifier:MBXSimpleStyleReuseIdentifier];
if (!view) {
view = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:MBXSimpleStyleReuseIdentifier];
}
view.image = ((MBXPointAnnotation *)annotation).image;
view.canShowCallout = YES;
return view;
}
return nil;
}
#pragma mark - MBXRasterTileOverlayDelegate implementation
- (void)tileOverlay:(MBXRasterTileOverlay *)overlay didLoadMetadata:(NSDictionary *)metadata withError:(NSError *)error {
// This delegate callback is for centering the map once the map metadata has been loaded
if (error) {
LOG(@"Failed to load metadata for map ID %@ - (%@)", overlay.mapID, error?error:@"");
[self showOfflineMap];
} else {
[_mapView mbx_setCenterCoordinate:overlay.center zoomLevel:overlay.centerZoom animated:NO];
_startingZoom = overlay.centerZoom;
_startingRegion = _mapView.region;
_readyToDownload = YES;
[self downloadMap];
}
}
- (void)tileOverlay:(MBXRasterTileOverlay *)overlay didLoadMarkers:(NSArray *)markers withError:(NSError *)error {
// This delegate callback is for adding map markers to an MKMapView once all the markers for the tile overlay have loaded
if (error) {
LOG(@"Failed to load markers for map ID %@ - (%@)", overlay.mapID, error?error:@"");
} else {
[_mapView addAnnotations:markers];
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment