Created
August 27, 2014 22:28
-
-
Save respectTheCode/421c329f3551321099d4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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