Demo of using MKOverlayView in iOS 4.0+ to render custom tile server overlays. (Last updated in 2012, you probably want to look elsewhere for modern code examples.)
Fetching latest commit…
Cannot retrieve the latest commit at this time.


iOS Custom Map Layer Example

A barebones demo app that demonstrates the use of some new MapKit functionality in iOS 4.0.:

The MKOverlay protocol and MKOverlayView class and how to use these to render custom tile layers a la Google Maps API. (i.e. Google Maps-compatible tile layers from Mapnik/Tilecache, gheat, etc.) Examples include tilesets from OpenStreetMap and MapBox.

(Caveat: the OpenStreetMap renders opaquely over the default Google layer, it does not replace it.)

Comments and feedback are welcome.



I refactored django-gheat as a side project and I’ve been working on iOS development a bit lately and was seeking a slick way to plug the django-gheat demo tileserver into the iPhone. The Google Maps API just doesn’t have enough performance in the browser to make for a decent user experience.

Some conversation threads recommended combining a UIScrollView with CATiledLayer, but this seemed unwieldy to couple with the existing MapKit framework.

Lo and behold, iOS 4.0 added custom overlay functionality to MapKit, though I have not seen any mention or example of it’s use to date.


The code is generally commented thoroughly. I am not an expert in cartography, so my knowledge of map projections and some of the calculations within the code are to be taken with a grain of salt.

CustomOverlayView compensates for [[UIScreen mainScreen] scale], or the iPhone 4’s pixel doubling. The view applies the screen scale factor, creating a situation as if the screen were twice as large. Because MapKit loads pixel-doubled tiles but maintains the same viewport, CustomOverlayView renders tiles of the next (or scale-appropriate) zoom level to maintain a one-to-one mapping with MapKit’s own tiles.

The [MKOverlayView -canDrawMapRect…] and [MKOverlayView -drawMapRect…] methods rely on asynchronously downloading tiles as requested (by -canDrawMapRect) into cache, and then using that cache in the -drawMapRect method after the success callback notifies MapKit to try the tile again.