Concepts and Constraints
This guide provides an overview of key concepts and limits to consider when implementing offline maps in your iOS app using the Maps SDK for iOS. Understanding offline maps can help you design a better user experience and manage storage effectively.
How Offline Maps Work
Under normal circumstances, the Maps SDK for iOS fetches map data (vector or raster tiles) and style resources (style JSON, sprites, fonts, etc.) from Mapbox servers over the internet as needed to render the map. If your users lose internet connectivity, the map will not be able to load new data and parts of the map may appear blank or incomplete. This is particularly common when zooming or panning to new areas, as displaying map information in these areas requires fetching new tiles. In contrast, areas that the Maps SDK has already loaded, generally around the viewport, may still be visible due to caching.
Offline Maps are designed to work seamlessly with the regular map experience, providing map data from local storage when the device is offline. Offline data must be loaded in advance, but no special action or handling is required when the device goes offline.
To render a Mapbox map without internet connectivity, the device must have access to both style data and map data for areas the user wants to view offline. The Maps SDK for iOS provides APIs to download and manage both types of data for offline use.
Offline Data Concepts
Implementing offline maps means managing offline data. Which geographic areas, zoom levels, and styles to make available offline is up to you and your app's use case.
The first three concepts to learn are Style packs, Tile regions, and Tile packs:
| Concept | Purpose | Offline Data |
|---|---|---|
| Style pack | Non-tile resources required to render a map style offline | Style JSON, sprites, fonts, 3D models, and other assets the style depends on |
| Tile pack | Efficiently stored tiles for a given area and zoom range used to render map features | Vector or raster tiles for roads, buildings, terrain, and other map features; stored as one or more tile packs per region |
| Tile region | Configuration object defining a geographic area + zoom range to make available offline | Not applicable, the tile region is used to determine which tile packs are needed |
Style Packs
The style pack contains all non-tile resources required to render a map style offline. It is usually much smaller than map data, typically only a few megabytes, and only needs to be downloaded once per style.
For example, you may define several regions for offline use in your app, but if they all use the same map style, the style pack for that style only needs to be downloaded once.
Tile Packs
Tile packs are collections of map tiles from a tileset, but are grouped using a predefined scheme of zoom ranges. These groupings are optimized for efficient storage and retrieval, but they also mean that you may have to download more data than necessary to cover your desired zoom levels. Only tilesets hosted on Mapbox servers are supported for offline use. You can either use Mapbox tilesets, or custom tilesets you have created with Mapbox Tiling Service.
The earth is represented by billions of tiles from zoom level 0 to 16. To manage this large number of tiles, tile packs group tiles into ranges based on their zoom levels. Each tile pack has an index zoom that defines the top-level zoom for the pack, and a corresponding min zoom and max zoom that define the range of zoom levels included in the pack.
| Purpose | Index Zoom | Min Zoom | Max Zoom | Tiles per pack |
|---|---|---|---|---|
| Global coverage | 0 | 0 | 5 | ~1.4K tiles |
| State information | 6 | 6 | 10 | ~341 tiles |
| Town information | 11 | 11 | 14 | ~85 tiles |
| Building detail | 12 | 15 | 16 | ~320 tiles |
You as a developer do not control the download and management of tile packs directly. Instead, you define tile regions that specify the geographic area and zoom range you want to make available offline, and the SDK automatically determines which tile packs are needed to cover that area and zoom range.
Limiting your tile regions to fit within the fewest number of tile pack zoom ranges can help decrease the amount of data users need to download and store on their devices.
Tile packs can vary significantly in size depending on the area covered and the zoom levels included, often ranging from tens to hundreds of megabytes.
Tile Regions
Tile regions are how you define the geographic area and zoom range you want to make available offline, along with the style to use for that region. You define a tile region, and the SDK automatically determines which tile packs are needed to cover that area and zoom range, fetching and storing them on the device.
To define a tile region, you specify:
- A Geometry: A GeoJSON geometry for the area to be available offline. This can be a point, line, polygon, or multi-polygon. The SDK will compute which tiles intersect this geometry to determine which tile packs to download.
- A Zoom Range: The minimum and maximum zoom levels you want to make available offline. The SDK will determine which tile packs are needed to cover this zoom range based on the predefined zoom ranges of the tile packs.
- Metadata (optional): Custom key-value pairs that can be used to store information about the region, such as a name, description, or download date. This metadata can be retrieved later to help manage offline regions.
The geometry you use will have major implications for the amount of data you need to download and store. For example, defining a bounding box polygon means the amount of data required for higher zoom ranges can grow exponentially. With a point, linestring, or more complex polygon, you can limit the area more precisely and reduce the amount of data needed.
For example, compare the tile pack requirements for a polygon covering a city versus a linestring following a river through the same area. The polygon will require downloading all tiles that intersect that polygon, which may include many tiles outside the visible area. The linestring, will only require tiles that intersect the line, significantly reducing the amount of data needed.
The Tile Store
The tile store manages retrieving and organizing of tile packs. The Maps SDK uses the tile store for offline data such as tile regions or style pack resources. The tile store does not share tiles with the disk cache (see note on disk cache below). Although the Offline Manager manages style packs and handles creating tileset descriptors, it is the job of the tile store to manage tile regions.
When a user loads and interacts with a map on their device, any visible tiles
and style resources (style JSON, fonts, sprites, etc.) are placed in the
device's disk cache, which is located in the maps data directory defined in
the MapsResourceOptions.dataPath. The disk cache observes when these
resources are used and makes intelligent guesses about which resources may be
needed again.
When a user revisits a place on the map, it will load more quickly if the associated resources are still present in the disk cache, because the device will not have to request those resources from the server to render the map.Resources are not permanently stored in the disk cache. There are no guarantees about how long these resources will be cached, but the least-recently used resources are normally removed to make room for newer resources.
Tileset Descriptors
A tileset descriptor contains metadata about the tilesets, zoom ranges, and pixel ratio that cached tile packs should include. You can create tileset descriptors with the Offline Manager. Tileset descriptors are one input used to define a tile region.
Offline Manager
The Offline Manager API provides a configuration interface and entrypoint for offline map functionality. It is used to manage style packs and to produce tileset descriptors that can be used with a tile store.
User Interface for Managing Offline Maps
There are no built-in User Interface components for managing offline maps in the Maps SDK for iOS. You will need to build your own UI to allow users to select areas for offline use, track download progress, and trigger updates or deletions of offline data.
You can see sample UI for managing offline map downloads in the Use offline maps in an iOS app tutorial.
Limits
The cumulative number of unique tile packs used in the tile regions cannot be greater than 750. The SDK will not load tile regions if it would lead to exceeding the tile pack limit.
Our terms of service do not allow developers or end users to redistribute offline maps downloaded from Mapbox servers. Users of the SDK must retrieve Mapbox data intended for offline use from Mapbox servers--the data may not be preloaded, bundled or otherwise redistributed.
Understanding and configuring offline behavior
Understanding the default behavior and customization options of the Maps SDK's offline functionality can allow you to optimize your app's offline functionality and manage it more flexibly.
Each Map instance stores files for both the disk cache and tile store in a default location (normally, inside the application cache folder). To override the default, you can provide a custom data path for the disk cache and a tile store instance. There is only ever one tile store for each unique file path.
The Offline Manager can be configured using MapboxMapsOptions. You can completely disable the tile store by setting MapboxMapsOptions.tileStoreUsageMode to .disabled. In this case, a tile store will not be created and tile region functionality will not be available.
By default, a tile store is read-only and the Maps SDK only interacts with it to check for tiles it needs. If the necessary tile is not in the tile store, the SDK will request the individual tile and store it in the disk cache instead of the tile store. By default, the SDK will not fetch tile packs in scenarios like this, where a tile is not available locally and must be retrieved.
You can enable implicit tile pack loading by setting the MapboxMapsOptions.tileStoreUsageMode option. When set to .readAndUpdate, the map engine will use the tile store for loading tile packs rather than loading tiles individually. Only tile packs will be used. This option can be useful if the map trajectory is predefined and the user cannot pan freely (for example, navigation use cases). In these circumstances, it is more efficient to use tile packs for all map data loading instead of allowing the map to request arbitrary tiles.
Tile store disk quota
By default, there is no limit to the size of a tile store. A quota can be configured with the TileStoreOptions.diskQuota option.
The tile store will refuse to store new data on disk if it would cause the quota to be exceeded. To make room for new content, tile packs with the nearest expiration dates that aren't shared by another tile region will be removed before the quota is reached. By default, eviction begins when the tile store reaches 50% of the configured quota (for example, at 50 MB for a 100 MB quota) to prevent the quota from being exceeded.
Before Mapbox Maps SDK 11.2.0, removal of tile packs was triggered only after the quota was exceeded. Since tile packs that are part of a tile region that wouldn't be removed, this could cause the tile store to grow permanently over the specified quota.
For instance, if you set TileStoreOptions.diskQuota to 500 MB, eviction will begin when the tile store size reaches 250 MB (50% of quota). The tile store will start evicting tile packs with the nearest expiration date which are not part of any region to try to keep the size under 250 MB. In case all tile packs belong to some region and nothing can be evicted, the tile store may keep growing and use the entire quota of 500 MB. After that, no new tile packs can be added to the tile store and some regions would need to be removed or TileStoreOptions.diskQuota would need to be increased.
// Set a quota of 100 MB. Tile store will begin evicting tile packs at 50 MB (50% of quota)
// and will not allow saving new tile packs when tile store size exceeds 100 MB
tileStore.setOptionForKey(TileStoreOptions.diskQuota, value: 100 * 1024 * 1024)
Tile count granularity
The tile store loads and stores tiles in tile packs. Each tile pack has a predefined zoom range and contains all child tiles within that range. The tile leveling scheme for a tileset is determined in the TileJSON. The default tile pack zoom ranges are:
- Global coverage: 0 - 5
- Regional information: 6 - 10
- Local information: 11 - 14
- Streets detail: 15 - 16
When specifying minimum and maximum zoom levels as part of the TilesetDescriptorOptions, the actual zoom levels of the retrieved data will be determined by these ranges. For example, if you set minZoom to 8 and maxZoom to 15, the downloaded tiles will include zoom levels ranging from 6 to 16.
Supported tiled sources
Tile regions support only the tiled sources whose tile endpoint URLs correspond to the Mapbox Vector/Raster tile v4 URL schema or Mapbox Raster DEM tile v1 URL schema. Your tiled source probably uses the v4 URL schema unless it is more than a few years old.
Potential risks on updating the offline style
Changing the style currently in use in offline scenarios should be executed with great care to make sure that the existing loaded style packages and tile regions continue to function correctly after the update.
Modifications to the style layers that interact with the current style sources are typically safe. However, modifications to the style sources entail adjustments to the tiles in use, which could potentially cause previously-loaded tile regions to become incompatible with the updated style.
Composited sources
While source compositing helps to load the map faster during online usage, it introduces potential risks for offline scenarios.
In general, we recommend disabling source compositing when creating a styles for offline usage to avoid known limitations listed below.
Composited tile components do not go beyond scale
When a composited source consists of two or more components with different maximum zoom levels and the camera is displaying a zoom level higher than the maximum zoom of one of the source components then data from that particular source component will not be rendered.
This limitation arises because, for offline usage, source compositing is performed on the client side (from the stored tile packs data), and the implementation is constrained in comparison to server-side source compositing logic.