Overlays

An overlay is an element visually representing geographical information, which you can freely place on your map. The NAVER Maps SDK provides various types of overlays, such as markers, info windows and shapes. For more information, refer to the documentation of each overlay.

Add and remove overlays

Create objects

All overlays except location overlays can be created just like a general class object.

The following code example creates a marker object.

let marker = NMFMarker()

Swift

let marker = NMFMarker()

Objective-C

NMFMarker *marker = [NMFMarker new];

You can get a location overlay object, with the locationOverlay property of NMFMapView.

The following code example gets a location overlay object.

let locationOverlay = mapView.locationOverlay

Swift

let locationOverlay = mapView.locationOverlay

Objective-C

NMFLocationOverlay *locationOverlay = self.mapView.locationOverlay;

Add overlays

All overlays except location overlays can be added to the map by specifying the mapView property. For information on how to add location overlays to the map, refer to Location Overlays.

The following code example adds a marker to the map.

marker.mapView = mapView

Swift

marker.mapView = mapView

Objective-C

marker.mapView = self.mapView;

Besides the mapView property, you can also use the -openWithMarker: method, to open an info window for your map or markers.

The following code example adds an info window to a marker.

infoWindow.open(with: marker)

Swift

infoWindow.open(with: marker)

Objective-C

[infoWindow openWithMarker:marker];

As the mapView is the property of an overlay, one overlay cannot be displayed on two or more maps at the same time. If you newly set the mapView property to an overlay that is already on the map, the overlay disappears from the previous map and appears on the new map.

Remove overlays

All overlays except location overlays can be removed from the map by setting the mapView property to nil. For information on how to remove location overlays from the map, refer to Location Overlays.

The following code example removes a marker from the map.

marker.mapView = nil

Swift

marker.mapView = nil

Objective-C

marker.mapView = nil;

Besides the mapView property, you can also use the -close method to close an info window.

The following code example closes an info window.

infoWindow.close();

Swift

infoWindow.close();

Objective-C

[infoWindow close];

Multithreading

An overlay object can be created by any thread. However, since an overlay’s properties are not thread-safe, they cannot be accessed simultaneously by multiple threads. In particular, properties of an overlay added to a map should be accessed by the main thread, otherwise NSObjectInaccessibleException occurs. Note that the exception does not occur even if other threads access the properties of the overlay that is not added to a map.

Therefore, when handling a large number of overlays, you can use a background thread to create an object and set initial options while using the main thread only to add an overlay to the map for efficiency. The following code example creates 1,000 markers and set their properties in a background thread and adds them to the map.

DispatchQueue.global(qos: .default).async {
    // Background thread
    var markers = [NMFMarker]()
    for index in 1...1000 {
        let marker = NMFMarker(position: ...)
        marker.iconImage = ...
        marker.captionText = ...
        markers.append(marker)
    }

    DispatchQueue.main.async { [weak self] in
        // Main thread
        for marker in markers {
            marker.mapView = self?.mapView
        }
    }
}

Swift

DispatchQueue.global(qos: .default).async {
    // Background thread
    var markers = [NMFMarker]()
    for index in 1...1000 {
        let marker = NMFMarker(position: ...)
        marker.iconImage = ...
        marker.captionText = ...
        markers.append(marker)
    }

    DispatchQueue.main.async { [weak self] in
        // Main thread
        for marker in markers {
            marker.mapView = self?.mapView
        }
    }
}

Objective-C

__block ViewController *weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // Background thread
    NSMutableArray<NMFMarker *> *markers = [NSMutableArray array];
    for (NSInteger i = 0; i < 1000; i++) {
        NMFMarker *marker = [NMFMarker markerWithPosition:...];
        marker.iconImage = ...;
        marker.captionText = ...;
        [markers addObject:marker];
    }

    dispatch_async(dispatch_get_main_queue(), ^(){
        // Main thread
        for (NMFMarker *marker in markers) {
            marker.mapView = weakSelf.mapView;
        }
    });
});

Bitmap

Most overlays including markers, info windows, location overlays, ground overlays and path overlays use bitmap images. To use bitmap images for your overlays, you should create an NMFOverlayImage object.

Create NMFOverlayImage objects

NMFOverlayImage is an immutable class representing a bitmap image that can be used as an icon. Using the factory methods defined in the NMFOverlayImage class, you can create an instance from image assets, UIImage, and NSBundle. The list below describes some factory methods.

The following code example creates an NMFOverlayImage object from the image asset resource.

let image = NMFOverlayImage(name: "marker_icon")

Swift

let image = NMFOverlayImage(name: "marker_icon")

Objective-C

NMFOverlayImage *image = [NMFOverlayImage overlayImageWithName:@"marker_icon"];

Set the NMFOverlayImage object in the property of the overlay that needs a bitmap, and the image is reflected. For more information, refer to the documentation of each overlay.

The following code example sets a marker icon.

let image = NMFOverlayImage(name: "marker_icon")
marker.iconImage = image

Swift

let image = NMFOverlayImage(name: "marker_icon")
marker.iconImage = image

Objective-C

NMFOverlayImage *image = [NMFOverlayImage overlayImageWithName:@"marker_icon"];
marker.iconImage = image;

NMFOverlayImage using UIView

You can also create an NMFOverlayImage using a custom view. Implement an NMFOverlayImageDataSource protocol in a custom view to be used as an NMFOverlayImage, and add it as a dataSource of the NMFOverlay object to use.

Memory management

Since the NMFOverlayImage object handles bitmap images, you should carefully manage memory. If multiple overlays use the same image, only one NMFOverlayImage instance is needed.

The following code example shows a bad case where marker1 and marker2 share one bitmap image but marker3 and marker4 each have the same bitmap image.

// Good: marker1 and 2 share the same bitmap.
let image = NMFOverlayImage(name: "marker_icon")
marker1.iconImage = image
marker2.iconImage = image

// Bad: marker3 and 4 each have the same bitmap.
marker3.iconImage = NMFOverlayImage(name: "marker_icon")
marker4.iconImage = NMFOverlayImage(name: "marker_icon")

Swift

// Good: marker1 and 2 share the same bitmap.
let image = NMFOverlayImage(name: "marker_icon")
marker1.iconImage = image
marker2.iconImage = image

// Bad: marker3 and 4 each have the same bitmap.
marker3.iconImage = NMFOverlayImage(name: "marker_icon")
marker4.iconImage = NMFOverlayImage(name: "marker_icon")

Objective-C

// Good: marker1 and 2 share the same bitmap.
NMFOverlayImage *image = NMFOverlayImage overlayImageWithName:@"marker_icon"];
marker1.iconImage = image;
marker2.iconImage = image;

// Bad: marker3 and 4 each have the same bitmap.
marker3.iconImage = [NMFOverlayImage overlayImageWithName:@"marker_icon"];
marker4.iconImage = [NMFOverlayImage overlayImageWithName:@"marker_icon"];

Note that if NMFOverlayImage objects are created from UIImage objects, and the NMFOverlayImage objects refer to the same UIImage, the instances share the same bitmap even if they are different.

The following code example shows a case where marker1, marker2, marker3, and marker4 share the same bitmap.

// Good: marker1 and 2 share the same bitmap.
let image = NMFOverlayImage(image: bitmap)
marker1.iconImage = image
marker2.iconImage = image

// OK: marker3 and 4 each use different NMFOverlayImage objects but refer to the same resource, so they share the same bitmap.
marker3.iconImage = NMFOverlayImage(image: bitmap)
marker4.iconImage = NMFOverlayImage(image: bitmap)

Swift

// Good: marker1 and 2 share the same bitmap.
let image = NMFOverlayImage(image: bitmap)
marker1.iconImage = image
marker2.iconImage = image

// OK: marker3 and 4 each use different NMFOverlayImage objects but refer to the same resource, so they share the same bitmap.
marker3.iconImage = NMFOverlayImage(image: bitmap)
marker4.iconImage = NMFOverlayImage(image: bitmap)

Objective-C

// Good: marker1 and 2 share the same bitmap.
NMFOverlayImage *image = [NMFOverlayImage overlayImageWithImage:bitmap];
marker1.iconImage = image;
marker2.iconImage = image;

// OK: marker3 and 4 each use different OverlayImage objects but refer to the same resource, so they share the same bitmap.
marker3.iconImage = [NMFOverlayImage overlayImageWithImage:bitmap];
marker4.iconImage = [NMFOverlayImage overlayImageWithImage:bitmap];

If too many bitmap images are used for the map to handle, the map rendering becomes very slow with a log message saying "Overlay image atlas overflow" in the Xcode console. And if the memory usage is too high, the process will be terminated because of out of memory (OOM).

Stacking order of overlays

When multiple overlays are overlapped on the screen, an overlay with a higher stack order is displayed on top of those with lower stack orders. The stack order is specified depending on the type of an overlay by default, but can be changed.

Global z-index

The globalZIndex property specifies the stack order of an overlay. If globalZIndex is 0 or bigger, the overlay is drawn on top of symbols; if the property is smaller than 0, it is drawn beneath symbols. Note that an overlay is always drawn on top of the map background no matter how small globalZIndex is. The default globalZIndex values for each overlay type are as follows.

  • Info window: 400000
  • Location overlay: 300000
  • Marker: 200000
  • Arrowhead path overlay: 100000
  • (Map symbols)
  • Path: -100000
  • Shape (polygon, polyline, circle): -200000
  • Ground overlay: -300000
  • (Map background)

For example, a path is drawn on top of a shape, and beneath a symbol on the map by default. However, if the globalZIndex property of a path is set to 250000, it is drawn on top of markers and beneath a location overlay.

The following code example specifies the stacking order of three overlays, as polygon -> path -> marker.

polygon.globalZIndex = 150000
path.globalZIndex = 50000
marker.globalZIndex = -500000

Swift

polygon.globalZIndex = 150000
path.globalZIndex = 50000
marker.globalZIndex = -500000

Objective-C

polygon.globalZIndex = 150000;
path.globalZIndex = 50000;
marker.globalZIndex = -50000;

Global z-indexes specified

Local z-index

The zIndex property specifies the stack order of overlays with the same globalZIndex. If two overlays have the same globalZIndex value, an overlay with the higher zIndex is displayed on top of the other. For example, even if the zIndex of a marker is set to 1, and the zIndex of a ground overlay is set to 2, the marker is drawn on top of the ground overlay because the marker’s default globalZIndex is 200000, and that of the ground overlay is -300000. Since the default value of the zIndex property is 0 regardless of the type of an overlay, zIndex can be used more intuitively than globalZIndex to specify the stack order of overlays with the same type.

The following code example specifies the stacking order of three markers as yellow -> green -> blue.

yellowMarker.zIndex = 100
greenMarker.zIndex = 0
blueMarker.zIndex = -10

Swift

yellowMarker.zIndex = 100
greenMarker.zIndex = 0
blueMarker.zIndex = -10

Objective-C

yellowMarker.zIndex = 100;
greenMarker.zIndex = 0;
blueMarker.zIndex = -10;

Markers with z-indexes specified

Show and hide overlays

All overlays have the visibility and maximum/minimum zoom level properties. To hide an overlay temporarily or in a certain situation, use these properties, rather than the mapView property.

Visibility

Set hidden to YES to hide an overlay. The relation between the overlay and the map still remains the same.

The following code example hides an overlay.

overlay.hidden = true

Swift

overlay.hidden = true

Objective-C

overlay.hidden = YES;

Minimum and maximum zoom levels

Use minZoom and maxZoom to show an overlay at a specified zoom level. If the camera’s zoom level is out of the range between the minZoom and the maxZoom, the overlay is hidden.

The following code example sets an overlay to be shown only at the levels, between 12 and 16.

overlay.minZoom = 12
overlay.maxZoom = 16

Swift

overlay.minZoom = 12
overlay.maxZoom = 16

Objective-C

overlay.minZoom = 12;
overlay.maxZoom = 16;

Event

All overlays can receive and consume touch events. A touch event for overlays should be added to each overlay, not the map.

Touch event

Set overlayTouchHandler in the touchHandler property to receive a touch event for overlays. When an overlay is tapped, the block method implemented in the touchHandler is called with the tapped overlay object passed as a parameter.

The following code example sets a touch handler to display a log saying “Overlay is touched” whenever an overlay is tapped.

overlay.touchHandler = { (overlay: NMFOverlay) -> Bool in
    print("Overlay is touched")
    return true
}

Swift

overlay.touchHandler = { (overlay: NMFOverlay) -> Bool in
    print("Overlay is touched")
    return true
}

Objective-C

overlay.touchHandler =  ^BOOL(NMFOverlay *overlay) {
    NSLog(@"Overlay is touched");
    return YES;
};

Only one touch event listener can be added to an overlay. To remove the touch event listener, set the touchHandler property to nil.

The following code example removes the touch handler of an overlay.

overlay.touchHandler = nil

Swift

overlay.touchHandler = nil

Objective-C

overlay.touchHandler = nil;

A touch handler should be added to every overlay which needs to receive events. If an overlay has no touch handler added, a tap on the overlay is ignored. For example, if there are two overlays overlapped with each other and the one on top of the other does not have a touch handler added, the other one receives a touch event. If there is no overlapped overlay or a touch handler is not added, it is considered that the map is tapped.

Propagate and consume events

An overlay touch event can be propagated to the map. To propagate an event to the map, you should make touchHandler return NO. After the touchHandler returns NO, the -didTapMapView:LatLng: delegate method of the map is called. On the contrary, if the touchHandler returns YES, it is considered that the overlay consumes the event and thus the -didTapMapView:LatLng: of the map is not called.

In the following code example, marker1 propagates touch events and marker2 consumes them. Whereas both log messages, “Marker is touched” and “Map is touched” are displayed when the marker1 is tapped, only the log message, “Marker 2 is touched” is displayed when the marker2 is tapped.

marker1.touchHandler = { (overlay) -> Bool in
    print("Marker 1 is touched")
    // Propagates the event.
    return false
}

marker2.touchHandler = { (overlay) -> Bool in
    print("Marker 2 is touched")
    return true
}

func didTapMapView(_ point: CGPoint, latLng latlng: NMGLatLng) {
    print("Map is touched")
}

Swift

marker1.touchHandler = { (overlay) -> Bool in
    print("Marker 1 is touched")
    // Propagates the event.
    return false
}

marker2.touchHandler = { (overlay) -> Bool in
    print("Marker 2 is touched")
    return true
}

func didTapMapView(_ point: CGPoint, latLng latlng: NMGLatLng) {
    print("Map is touched")
}

Objective-C

marker1.touchHandler =  ^BOOL(NMFOverlay *overlay) {
    NSLog(@"Marker 1 is touched");
    // Propagates the event.
    return NO;
};

marker2.touchHandler =  ^BOOL(NMFOverlay *overlay) {
    NSLog(@"Marker 1 is touched");
    // Consumes the event.
    return YES;
};

- (void)didTapMapView:(CGPoint)point LatLng:(NMGLatLng*)latlng {
    NSLog(@"Map is touched");
}

Overlays can propagate an event only to the map. That is, even if there are multiple overlays or symbols overlapped under the overlay that triggers an event, it is not propagated to those overlays or symbols.

userInfo

The userInfo property specifies additional information for an overlay. This property is useful especially when combined with a touch event handler. Since touchHandler can use the information saved in userInfo to identify which overlay is tapped, you can let multiple overlays share a touch handler.

The following code example adds userInfo to marker1 and marker2 to share a touch handler.

let handler: overlayTouchHandler = { (overlay) -> Bool in
    print("Marker \(overlay.userInfo["tag"] ?? "tag") is touched")
    return false
}

marker1.userInfo = ["tag": 1]
marker2.userInfo = ["tag": 2]

marker1.touchHandler = handler
marker2.touchHandler = handler

Swift

let handler: overlayTouchHandler = { (overlay) -> Bool in
    print("Marker \(overlay.userInfo["tag"] ?? "tag") is touched")
    return false
}

marker1.userInfo = ["tag": 1]
marker2.userInfo = ["tag": 2]

marker1.touchHandler = handler
marker2.touchHandler = handler

Objective-C

overlayTouchHandler handler = ^BOOL(NMFOverlay *overlay) {
    NSLog(@"Marker %@ is touched", overlay.userInfo[@"tag"]);
    return NO;
};

marker1.userInfo = @{@"tag":@1};
marker2.userInfo = @{@"tag":@2};

marker1.touchHandler = handler;
marker2.touchHandler = handler;

results matching ""

    No results matching ""