Custom Raster Tiles
You can use the SDK for iOS to enhance maps with the custom raster tiles API — NMAMapTileLayer
.
Custom raster tiles are tile images that you can add to a map for enhancing the map with extra information over a large geographical area. If the application is set to display custom raster tiles, then users see them whenever they view a designated geographical area at a specified zoom level or range of zoom levels.
- Store custom raster tile images on a remote server and return URLs via the
NMAMapTileLayerDataSource mapTileLayer:urlForTileAtX:y:zoomLevel:
protocol method. - Provide raw bitmap data using the
NMAMapTileLayerDataSource mapTileLayer:requestDataForTileAtX:y:zoomLevel:
protocol method.
Dividing a Map and Using Tile Coordinates
NMAMapTileLayer
uses a scheme that divides the world map into tiles, specified by x, y and zoom level coordinates. This coordinate system is used by the NMAMapTileLayerDataSource
protocol when it requests tiles.
- at level 3: 8 x 8 = 64 tiles
- at level 4: 16 x 16 = 256 tiles
- continuing on until zoom level 20
For example, at zoom level 2, the world map would be divided up as follows:


The x and y parameters indicate which tile is being requested for the given zoom level.
You need to provide enough tile images to cover all the zoom levels you are supporting within a geographical area. You can restrict custom tile rendering to a specific NMAGeoBoundingBox
using the boundingBox
property of NMAMapTileLayer
. You can restrict the zoom level using showAtZoomLevel:
and related methods.
Supplying Tiles from a Web Server
- Host the appropriate number of tiles on a server according to the zoom levels and
NMAGeoBoundingBox
you are supporting. The tiles must be in either PNG or JPG format and should be sized at 256 x 256 or 512 x 512 pixels.Note: As long as your tiles conform to 256 by 256 or 512 by 512 pixels, theNMAMapView
can scale the image to fit the current map resolution. For example, if theuseHighResolutionMap
property is set toYES
(512 by 512 pixels) but your tiles are 256 by 256 pixels, theNMAMapView
enlarges your image tiles. - Create an object that derives from
NMAMapTileLayerDataSource
and implement themapTileLayer:urlForTileAtX:y:zoomLevel:method
to return a URL pointing to the specified tile on your server. - Create an
NMAMapTileLayer
object and set its properties to correspond with the tile data source server. At a minimum, set theboundingBox
andzoomLevel
properties to reflect the tiles hosted on your server. Set thedataSource
property. - Add the
NMAMapTileLayer
object to theNMAMapView
by calling theaddMapTileLayer:
method.
The following code snippet shows a class that renders the Queen Elizabeth Olympic Park in London. The park is displayed as a tile layer that is added to an NMAMapView
, and the raster tiles are served from the HERE server. To use this class, call [OlympicParkTileLayer addOlympicParkTileLayerToMapView:myMapView]
.
@interface OlympicParkTileLayer : NMAMapTileLayer <NMAMapTileLayerDataSource>
@end
@implementation OlympicParkTileLayer
+(void)addOlympicParkTileLayerToMapView:(NMAMapView*)mapView
{
OlympicParkTileLayer *tileLayer = [OlympicParkTileLayer new];
[mapView addMapTileLayer:tileLayer];
[mapView setGeoCenter:tileLayer.boundingBox.center
zoomLevel:14.0
withAnimation:NMAMapAnimationNone ];
}
-(id)init
{
if (self = [super init]) {
// Set the data source
self.dataSource = self;
// Limit the tiles to the bounding box supported by the server
NMAGeoBoundingBox *olympicParkBoundingBox =
[NMAGeoBoundingBox geoBoundingBoxWithTopLeft:[NMAGeoCoordinates
geoCoordinatesWithLatitude:51.557000 longitude:-0.042772]
bottomRight:[NMAGeoCoordinates geoCoordinatesWithLatitude:51.525941
longitude: 0.028296]];
self.boundingBox = olympicParkBoundingBox;
// Enable caching
self.cacheTimeToLive = 60 * 60 * 24; // 24 hours
self.cacheSizeLimit = 1024 * 1024 * 64; // 64MB
[self setCacheEnabled:YES withIdentifier:@"OlympicParkTileLayer"];
}
return self;
}
-(NSString *)mapTileLayer:(NMAMapTileLayer *)mapTileLayer
urlForTileAtX:(NSUInteger)x
y:(NSUInteger)y
zoomLevel:(NSUInteger)zoomLevel
{
// Return a URL for the specified tile
// This tile source is hosted by HERE Global B.V. and may be removed at any time
return [NSString stringWithFormat:
@"http://api.maps.example.org/maptiles/olympic_park/normal.day/%d/%d/%d.png",
zoomLevel,
y,
x ];
}
@end
Supplying Tiles as Bitmaps
You can choose to supply tiles as bitmaps if your app uses bundled static tiles, dynamically-generated tiles, or if the server that you are using for tile images requires authentication. In the third case, since NMAMapTileLayer
only uses simple HTTP GET requests to retrieve tile images, it is up to you to provide code that handles authentication and downloads the tiles. Once the tiles have been downloaded, you can use them as local bitmaps with the NMAMapTileLayer
class.
- Create an object that derives from
NMAMapTileLayerDataSource
and implements themapTileLayer:requestDataForTileAtX:y:zoomLevel:
method. - Create an
NMAMapTileLayer
object and set its properties to correspond with the tile data source. Set thedataSource
property. - Add the
NMAMapTileLayer
object to theNMAMapView
by calling theaddMapTileLayer:
method.
Caching Tiles
Tiles can be cached to the disk to improve performance and reduce data traffic in the URL fetching case.
When you enable caching, you must provide a cache identifier. This identifier must be unique for each NMAMapTileLayer
used within your application. Since the cache persists across app sessions, it is important to use the same identifier across sessions (by defining a constant, for example).
You can optionally limit the cache size and time-to-live for each cached tile. The cache can be cleared at any time by calling [NMAMapTileLayer clearCache]
. To be sure the cache is completely cleared first remove the NMAMapTileLayer
from the map view before calling [NMAMapTileLayer clearCache]
.
The following code enables disk caching with a 128MB maximum size and a tile time-to-live of 7 days:
NMAMapTileLayer *tileLayer = [[NMAMapTileLayer alloc]init];
tileLayer.dataSource = self; // Assuming self is a valid data source
[tileLayer setCacheEnabled:YES withIdentifier:@"MyUniqueTileCacheIdenfifier"];
tileLayer.cacheTimeToLive = 60 * 60 * 24 * 7; // 7 days
tileLayer.cacheSizeLimit = 1024 * 1024 * 128; // 128 MB
[mapView addMapTileLayer:tileLayer]; // NOTE: add to map view after setting tile properties
Performance Tips
- IMPORTANT: Set
NMAMapTileLayer
properties before adding the tile layer to the map view. Most properties ignore attempts to set them after being added to the view. - Ensure the properties you set on the tile layer match the data you are supplying via the
NMAMapTileLayerDataSource
protocol. - Do not block
NMAMapTileLayerDataSource
methods for extended periods of time. For example, if it takes a while to generate tiles on the fly move the processing to a separate GCD queue. - If requesting a specific tile is constantly failing consider implementing
mapTileLayer:hasTileAtX:y:zoomLevel:
, returningNO
. - Use the provided disk caching mechanism.