Markers

Markers are used to indicate specific locations on the map. The Map Display SDK provides a default icon, but a custom drawable can be used as well. Markers are added as annotations to the fully initialized TomTomMap object. To add the map to your app, see the Adding a map guide .

Import the following frameworks to continue with this guide:

import CoreLocation
import SwiftUI
import TomTomSDKCommon
import TomTomSDKMapDisplay

The first step is to create a MarkerOptions object that describes the properties of the marker. The most important property is the CLLocationCoordinate2D where the marker should be added. The other properties are optional.

let amsterdam = CLLocationCoordinate2D(latitude: 52.379189, longitude: 4.899431)
let markerOptions = MarkerOptions(coordinate: amsterdam)

Add a defined MarkerOptions to the TomTomMap . The marker will be displayed at the provided coordinates. The AnnotationsActions.addMarker(options:) method returns the instance of the added Marker . If the coordinates are invalid or adding the marker failed, the method will throw AnnotationServiceError.invalidCoordinate or AnnotationServiceError.failedToCreateAnnotation respectively.


Default marker

Customizing the marker

The appearance of the marker can be customized using MarkerOptions . It provides several properties to do this:

  • MarkerOptions.pinImage - Defines the image of the pin and its shape.
    markerOptions.pinImage = UIImage(systemName: "square.fill")
  • MarkerOptions.pinImageURI - Defines the pin image by specifying its URI. If it is set, the MarkerOptions.pinImage is ignored. To make it work, you also need COMPRESS_PNG_FILES and STRIP_PNG_TEXT set to NO in the Xcode build settings.
    markerOptions.pinImageURI = "pin-image-URI"
  • MarkerOptions.iconImage - The image displayed on the top of the pin.
    markerOptions.iconImage = UIImage(systemName: "bicycle")
  • MarkerOptions.iconImageURI - The icon image specified using a URI. If it is set, the MarkerOptions.iconImage is ignored. To make it work, you also need COMPRESS_PNG_FILES and STRIP_PNG_TEXT set to NO in the Xcode build settings.
    markerOptions.iconImageURI = "icon-image-URI"
  • MarkerOptions.isSelectable - Property which defines whether the marker is selectable. By default, every marker is set to be selectable.
    markerOptions.isSelectable = false

Custom marker

Marker fading and shrinking

To prevent the map becoming overloaded with markers, you can set custom fading and shrinking ranges. Use the AnnotationsActions.setMarkerDistanceFadingRange(range:) and AnnotationsActions.setMarkerDistanceShrinkingRange(range:) methods of the TomTomMap instance. Distances are in meters. For example:

map.setMarkerDistanceFadingRange(range: ClosedRange(uncheckedBounds: (
lower: Measurement<UnitLength>(value: 200, unit: .meters),
upper: Measurement<UnitLength>(
value: 500,
unit: .meters
)
)))
map
.setMarkerDistanceShrinkingRange(range: ClosedRange(uncheckedBounds: (
lower: Measurement<UnitLength>(
value: 200,
unit: .meters
),
upper: Measurement<UnitLength>(
value: 500,
unit: .meters
)
)))

You can also completely disable marker fading and shrinking by setting AnnotationsActions.isMarkersFadingEnabled and AnnotationsActions.isMarkersShrinkingEnabled to false.

map.isMarkersFadingEnabled = false
map.isMarkersShrinkingEnabled = false

Fading and Shrinking

Removing a marker

All the markers added to a specific instance of the TomTomMap can be removed using AnnotationsActions.removeAnnotations() . Note that this method removes all annotations added to the map, including shapes like Circle or Polygon .

map.removeAnnotations()

You can also remove a single marker by using AnnotationsActions.remove(annotation:) . Interacting with the reference to a removed marker will have no effect.

map.remove(annotation: marker)

Marker events

You can observe click events performed on markers via MapDelegate . To register these actions, override the following method. It provides the Annotation object of the marker that was clicked with its coordinates and the TomTomMap instance.

func map(_ map: TomTomMap, onInteraction interaction: MapInteraction) {
switch interaction {
case let .tappedOnAnnotation(annotation, coordinate):
/* YOUR CODE GOES HERE */
break
default:
break
}
}

Zooming to markers

The Map Display SDK provides simple methods for zooming a camera to markers. You can zoom to a view containing all of the markers that have been added to the TomTomMap .

map.zoomToMarkers()

You can also set the margin around the area to which the camera is zoomed. The margin is expressed in pixels.

map.zoomToMarkers(marginPx: 16)

Balloons

Balloons are popup views that appear on top of the map when the user taps a marker. They do not appear by default. To show a balloon, provide the MapDataSource delegate to its TomTomMap.dataSource property. It has a method for providing a UIView when an Annotation is selected.

func map(_: TomTomMap, viewForSelected marker: Annotation) -> UIView? {
guard let marker = marker as? Marker else { return nil }
let coordinates = marker.coordinate
let coordinatesText = "\(coordinates.latitude), \(coordinates.longitude)"
let annotationView =
UIHostingController(rootView: CustomMarkerBalloonView(locationCoordinates: coordinatesText))
return annotationView.view
}

The view for the marker balloon can be defined using SwiftUI , for example:

struct CustomMarkerBalloonView: View {
var locationCoordinates: String
var body: some View {
VStack(alignment: .center) {
Image(systemName: "mappin")
.font(.system(size: 48))
Text(locationCoordinates)
}
.padding()
}
}

Inside the previously described method, create a UIView that will represent the balloon.

func map(_: TomTomMap, viewForSelected marker: Annotation) -> UIView? {
guard let marker = marker as? Marker else { return nil }
let coordinates = marker.coordinate
let coordinatesText = "\(coordinates.latitude), \(coordinates.longitude)"
let annotationView =
UIHostingController(rootView: CustomMarkerBalloonView(locationCoordinates: coordinatesText))
return annotationView.view
}

Now if a Marker was set to be selectable, clicking on it causes the CustomMarkerBalloonView to appear above it. An Annotation can also be selected programmatically. To do this, call the AnnotationsActions.select(annotation:) method with the Marker as a parameter. You can deselect the Annotation in a similar way.

map.select(annotation: marker)
map.deselect(annotation: marker)

Custom ballon view