Select platform: [Android](https://developers.google.com/maps/documentation/android-sdk/tileoverlay.md.txt "View this page for the Android platform docs.") [iOS](https://developers.google.com/maps/documentation/ios-sdk/tiles.md.txt "View this page for the iOS platform docs.") [JavaScript](https://developers.google.com/maps/documentation/javascript/customoverlays.md.txt "View this page for the JavaScript platform docs.")

<br />

You can add images on top of your map as a Tile Layer. Tile Layers are
placed overtop of a map tile at a specific zoom level. With enough tiles, you
can supplement Google's map data for the entire map, at multiple zoom levels.

![](https://developers.google.com/static/maps/documentation/ios-sdk/images/ios-tiles.png)

## Introduction

Tile layers, sometimes referred to as Tile Overlays, let you superimpose
images on top of Google's base map tiles. Use this feature to add data,
such as points of interest or traffic information, and local imagery to
your app. When combined with the `kGMSTypeNone` map type,
tile layers effectively let you replace Google's base map data with your own.

Tile layers are useful when you want to add extensive imagery, typically
covering large geographical areas, to the map. By contrast, [ground
overlays](https://developers.google.com/maps/documentation/ios-sdk/overlays) are useful when you want to fix a single image at one
point on the map.

## Tile coordinates

The Maps API breaks up imagery at each zoom level into a set of square map
tiles, which are arranged in an ordered grid. When a map scrolls to
a new location, or to a new zoom level, the Maps API determines which tiles
are needed, and translates that into a set of tiles to retrieve.

In the Google implementation of the Mercator projection, the tile with
coordinate (0,0) is always at the northwest corner of the map, with `x` values
increasing from west to east and `y` values increasing from north to south.
Tiles are indexed using `x,y` coordinates from that origin. For example, at
zoom level 2, when the earth is divided up into 16 tiles, each tile can be
referenced by a unique `x,y` pair:

![Map of the world divided into four rows and four columns of tiles.](https://developers.google.com/static/maps/documentation/ios-sdk/images/tileCoordinates.png)

Each map tile is a 256x256 point square. At zoom level 0, the entire world is
rendered in a single tile. Each zoom level increases the magnification by a
factor of two. So, for example, at zoom level 1 the map is rendered as a 2x2
grid of tiles, at zoom level 2 as a 4x4 grid , and at zoom level 3 as an 8x8
grid. To create images for a tile layer, create a
256x256 point image for each tile at each zoom level that you want to support.

## Add a Tile Layer

1. Instantiate a [`GMSURLTileLayer`](https://developers.google.com/maps/documentation/ios-sdk/reference/objc/Classes/GMSURLTileLayer.md.txt) object, or a custom subclass of [`GMSTileLayer`](https://developers.google.com/maps/documentation/ios-sdk/reference/objc/Classes/GMSTileLayer.md.txt) or [`GMSSyncTileLayer`](https://developers.google.com/maps/documentation/ios-sdk/reference/objc/Classes/GMSSyncTileLayer.md.txt).
2. Optionally modify the `zIndex` property to adjust its position in relation to other tile layers.
3. Assign the `GMSTileLayer` object to the map by setting its `map` property.

The Maps SDK for iOS provides three classes that can be used to
implement a tile layer. With each class, you will need to define how to fetch
the correct map tile for a given set of `{x,y,zoom}` coordinates. The
available options are:

- Subclass `GMSSyncTileLayer`, providing the implementation of `tileForX:y:zoom` that returns `UIImage` instances.
- Subclass `GMSTileLayer`, providing the implementation of the asynchronous method `requestTileForX:y:zoom` that later calls back with a tile image.
- Use the existing class, `GMSURLTileLayer`, to fetch tiles automatically from URLs, providing the `GMSTileURLConstructor` block. `GMSURLTileLayer` is a concrete class that cannot be subclassed.

In the case of subclassing `GMSSyncTileLayer` or `GMSTileLayer`, providing a
`nil` tile result will tell the Maps SDK for iOS that data is
unavailable but that it may be available in the future. Alternatively,
return `kGMSTileLayerNoTile` to indicate that there is no tile at this
location.

For `GMSURLTileLayer`, returning `nil` from the `GMSTileURLConstructor` will
indicate that there is no tile at this location.

### Use GMSURLTileLayer to fetch tiles from URLs

The `GMSURLTileLayer` does not require subclassing, but you will have to
implement the `GMSTileURLConstructor` block. The below code shows how to
use `GMSURLTileLayer` to display the floor plan of a multistory building.


### Swift

```swift
let floor = 1

// Implement GMSTileURLConstructor
// Returns a Tile based on the x,y,zoom coordinates, and the requested floor
let urls: GMSTileURLConstructor = { (x, y, zoom) in
  let url = "https://www.example.com/floorplans/L\(floor)_\(zoom)_\(x)_\(y).png"
  return URL(string: url)
}

// Create the GMSTileLayer
let layer = GMSURLTileLayer(urlConstructor: urls)

// Display on the map at a specific zIndex
layer.zIndex = 100
layer.map = mapView
      
```

### Objective-C

```objective-c
NSInteger floor = 1;

// Create the GMSTileLayer
GMSURLTileLayer *layer = [GMSURLTileLayer tileLayerWithURLConstructor:^NSURL * _Nullable(NSUInteger x, NSUInteger y, NSUInteger zoom) {
  NSString *url = [NSString stringWithFormat:@"https://www.example.com/floorplans/L%ld_%lu_%lu_%lu.png",
                   (long)floor, (unsigned long)zoom, (unsigned long)x, (unsigned long)y];
  return [NSURL URLWithString:url];
}];

// Display on the map at a specific zIndex
layer.zIndex = 100;
layer.map = mapView;
      
```

<br />

### Subclass GMSSyncTileLayer to serve tiles as a UIImage

The `GMSSyncTileLayer` and `GMSTileLayer` are abstract classes designed to be
subclassed. You can use these classes to serve tiles as `UIImage`'s. The below
example shows how to render a custom image over some of the tiles on the map
by subclassing `GMSSyncTileLayer`.


### Swift

```swift
class TestTileLayer: GMSSyncTileLayer {
  override func tileFor(x: UInt, y: UInt, zoom: UInt) -> UIImage? {
    // On every odd tile, render an image.
    if (x % 2 == 1) {
      return UIImage(named: "australia")
    } else {
      return kGMSTileLayerNoTile
    }
  }
}

      
```

### Objective-C

```objective-c
@interface TestTileLayer : GMSSyncTileLayer
@end

@implementation TestTileLayer

- (UIImage *)tileForX:(NSUInteger)x y:(NSUInteger)y zoom:(NSUInteger)zoom {
  // On every odd tile, render an image.
  if (x % 2 == 1) {
    return [UIImage imageNamed:@"australia"];
  } else {
    return kGMSTileLayerNoTile;
  }
}

@end
      
```

<br />

To add the layer to your map, instantiate the object and set its map property.


### Swift

```swift
let layer = TestTileLayer()
layer.map = mapView
      
```

### Objective-C

```objective-c
GMSTileLayer *layer = [[TestTileLayer alloc] init];
layer.map = mapView;
      
```

<br />

### High DPI Tiles for Retina devices

You can use high DPI images with either [`GMSSyncTileLayer`](https://developers.google.com/maps/documentation/ios-sdk/reference/objc/Classes/GMSSyncTileLayer.md.txt)
or [`GMSURLTileLayer`](https://developers.google.com/maps/documentation/ios-sdk/reference/objc/Classes/GMSURLTileLayer.md.txt) by setting the `tileSize` to 512.
The `tileSize` property indicates the number of pixels that the returned tile
images will prefer to display as; this defaults to 256 --- the dimension
of a Google Maps tile on a non-Retina device.

If you are displaying normal DPI tiles on a high DPI device you can scale the
images up by setting `tileSize` to 512. Note that upscaling images may reduce
image quality, especially for fine lines or text. For best results, match the
`tileSize` and image DPI to the display. Maps shown on a Retina device will
look their best when displaying high DPI images with a `tileSize` of 512;
while maps shown on a non-Retina device will look great with normal images
and the default `tileSize` of 256.

> [!NOTE]
> **Note:** Values less than 256 are not recommended for Retina devices.

### Clear stale tiles

If the tiles provided by the layer become 'stale', then the method
`clearTileCache` should be called on the layer to force a refresh. This will
cause all of the tiles on this layer to be reloaded.


### Swift

```swift
layer.clearTileCache()
      
```

### Objective-C

```objective-c
[layer clearTileCache];
      
```

<br />