iOS SDK Guide

Gtel Maps iOS SDK

GtelMap iOS SDK provides a map integration API suite for iOS applications, featuring a centralized interaction architecture centered on GtelMapView. The SDK enables applications to initialize and manage maps, execute operations via apply(input:), and receive status updates, operation results, and map-related events through GtelMapViewDelegate.GtelMap SDK iOS cung cấp bộ API tích hợp bản đồ dành cho ứng dụng iOS, với kiến trúc tương tác tập trung thông qua GtelMapView. SDK hỗ trợ ứng dụng khởi tạo và quản lý bản đồ, thực hiện các thao tác thông qua apply(input:), đồng thời tiếp nhận trạng thái, kết quả xử lý và các sự kiện liên quan đến bản đồ thông qua GtelMapViewDelegate.

InfoThông tin ValueGiá trị Integration notesGhi chú tích hợp
SDKSDK GtelMapSDK Add GtelMapSDK to your application target, then import the SDK with import GtelMapSDK to use its APIs.Thêm GtelMapSDK vào target của ứng dụng, sau đó import SDK bằng import GtelMapSDK để sử dụng các API của SDK.
Guide versionPhiên bản guide 1.1 Added: GtelRouteNavigationViewController for navigation; POI interaction and display APIs; Map Style customization APIs; camera control utilities; door-to-door routing support; and implementation examples for Geofencing and Isochrone.Bổ sung: GtelRouteNavigationViewController cho chức năng dẫn đường; API thao tác và hiển thị POI; API tùy biến kiểu hiển thị bản đồ (Map Style); các tiện ích điều khiển camera; hỗ trợ dẫn đường từ điểm xuất phát đến điểm đích (door-to-door routing); cùng các ví dụ triển khai Geofencing và Isochrone.
PlatformNền tảng iOS 14.0 or lateriOS 14.0 trở lên The package currently declares iOS 14.0 as the minimum deployment target.SDK tương thích với iOS 14.0 trở lên.
UI frameworkUI framework UIKit, SwiftUI Use GtelMapView directly in UIKit or GtelMapSwiftUIView in SwiftUI.Dùng GtelMapView trực tiếp trong UIKit hoặc GtelMapSwiftUIView trong SwiftUI.
Installation methodCách cài đặt Vendor binary packageVendor binary package See details in Installation.Xem chi tiết tại phần Cài đặt.

What the SDK doesCác tính năng được SDK hỗ trợ

GtelMapViewPublic UIView for displaying maps, markers, routes, search results, and overlays.View chính để hiển thị bản đồ, marker, vẽ đường đi, kết quả tìm kiếm và lớp phủ.
GtelMapViewInputInput container for passing parameters and commands to the map view using apply(input:).Gửi lệnh và tham số đến bản đồ thông qua hàm apply(input:).
GtelMapViewDelegateDelegate interface for handling map events, user gestures, search, routing, and error callbacks.Lắng nghe sự kiện bản đồ, thao tác chạm, tìm kiếm, dẫn đường và xử lý lỗi.
GtelMapConfigurationRuntime configuration for initializing the SDK before creating a map view.Cấu hình API key và thiết lập SDK khi khởi động ứng dụng.
GtelMapClientPublic service facade for geocoding, route, weather, static map, snap, isochrone, and geofencing calls that do not need a map instance.Gọi trực tiếp các dịch vụ tìm kiếm, geocoding, dẫn đường, thời tiết khi không cần vẽ bản đồ.
GtelPlaceSearchViewControllerUIKit search UI backed by GtelMapClient.shared.autocomplete.Màn hình tìm kiếm địa điểm có sẵn của SDK.
UIKit ComponentsReusable native UIKit UI for style selection, nearby categories, weather details, route summaries, and multi-stop editing.Các giao diện có sẵn: chọn style, tìm kiếm xung quanh, thời tiết, tóm tắt lộ trình.
Gtel Maps SDK map overview screen
Map overview.Tổng quan bản đồ.
Search panel showing search results
Search results.Kết quả tìm kiếm.
Route rendered on the map
Route overlay.Lớp phủ tuyến đường.
  1. Add GtelMapSDK.xcframework to the app target and set it to Embed & Sign.Thêm GtelMapSDK.xcframework vào target ứng dụng và thiết lập Embed & Sign.
  2. Configure the SDK before the first GtelMapView is created.Cấu hình SDK trước khi tạo GtelMapView đầu tiên.
  3. Create GtelMapView, assign gtelMapDelegate, then send feature requests through apply(input:).Tạo GtelMapView, gắn gtelMapDelegate, rồi gửi yêu cầu bằng apply(input:).
  4. Use GtelMapClient.shared for service calls that feed host-owned UI or background workflows.Dùng GtelMapClient.shared khi ứng dụng cần lấy dữ liệu cho giao diện riêng hoặc xử lý nền.
This documentation covers public APIs provided via GtelMapView, GtelMapViewDelegate, and GtelMapClient. Internal implementation details and backend credentials are excluded for security.Tài liệu này chỉ hướng dẫn các API công khai qua GtelMapView, GtelMapViewDelegateGtelMapClient. Chi tiết máy chủ và thông tin bảo mật không được đưa vào guide.

InstallationCài đặt

Use the provided vendor binary package. The host app only adds GtelMapSDK.xcframework to the app target. All internal SDK content needed at runtime is packaged inside the framework.Dùng gói binary được cung cấp. Ứng dụng chỉ cần thêm GtelMapSDK.xcframework vào app target; mọi nội dung nội bộ mà SDK cần khi chạy đều đã được đóng gói sẵn trong framework.

Binary package layoutCấu trúc binary package

GtelMapSDKVendor/
  GtelMapSDK.xcframework
  README.md
  manifest.json

Add GtelMapSDK.xcframeworkThêm GtelMapSDK.xcframework

  1. Open the host app project or workspace in Xcode.Mở project hoặc workspace của ứng dụng trong Xcode.
  2. Drag GtelMapSDKVendor/GtelMapSDK.xcframework into the project navigator.Kéo GtelMapSDKVendor/GtelMapSDK.xcframework vào project navigator.
  3. In Xcode's add-file dialog, enable Copy items if needed and tick the host app target in Add to targets.Trong hộp thoại thêm file của Xcode, bật Copy items if needed và tích chọn app target ở mục Add to targets.
  4. Open the app target General > Frameworks, Libraries, and Embedded Content and set GtelMapSDK.xcframework to Embed & Sign.Mở app target General > Frameworks, Libraries, and Embedded Content và đặt GtelMapSDK.xcframeworkEmbed & Sign.
Package itemThành phần package Handled byXử lý bởi Build destinationĐích trong build output
GtelMapSDK.xcframeworkHost adds to app targetHost thêm vào app targetFrameworks, Libraries, and Embedded Content
Internal runtime contentNội dung runtime nội bộGtelMapSDK.xcframeworkLinked and embedded inside GtelMapSDK.frameworkĐã link và nhúng bên trong GtelMapSDK.framework

Import SDKKhai báo module SDK

import UIKit
import GtelMapSDK

Runtime configuration valuesCác giá trị cấu hình runtime

Keep real values outside committed source. The public guide shows only where the host app supplies configuration.Không commit giá trị thật vào source. Guide chỉ chỉ ra nơi ứng dụng truyền cấu hình cho SDK.

KeyKeyRequiredBắt buộcDescriptionMô tả
GTELMapAccessTokenYesRead from the host app Info.plist by GtelMapConfig.GtelMapConfig đọc giá trị này từ Info.plist của ứng dụng.
weatherApiKeyOnly for weatherChỉ khi dùng weatherSet via GtelMapConfiguration(weatherApiKey:) in AppDelegate. Required only when the host app calls weather helpers.Truyền qua GtelMapConfiguration(weatherApiKey:) trong AppDelegate. Chỉ cần khi ứng dụng dùng tính năng thời tiết.
apiVersionNoKhôngSet via GtelMapConfiguration(apiVersion:) in AppDelegate. Defaults to "1.1" when not provided.Set qua GtelMapConfiguration(apiVersion:) trong AppDelegate. Mặc định "1.1" nếu không cung cấp.

Location permissionQuyền vị trí

Only declare the location usage description if the host app uses the user's location, focuses the camera on the current location, or uses navigation.Chỉ khai báo mô tả quyền vị trí nếu ứng dụng dùng vị trí người dùng, đưa camera tới vị trí hiện tại hoặc dùng dẫn đường.

<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs your location to display the map and provide directions.</string>

Initialization & configKhởi tạo & cấu hình

Configure the SDK once during the app launch phase, before any screen creates a GtelMapView.Cấu hình SDK một lần trong giai đoạn app launch, trước khi bất kỳ màn hình nào tạo GtelMapView.

import UIKit
import GtelMapSDK

@main
final class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        GtelMapConfig.configure(GtelMapConfiguration(
            apiVersion: "1.1",
            weatherApiKey: "YOUR_WEATHER_API_KEY",
            ui: GtelMapUIConfiguration(
                titleColor: .black,
                titleSize: 13,
                subTitleColor: .gray,
                subTitleSize: 11,
                backgroundColor: .white
            ),
            size: GtelMapSizeConfiguration(
                closeButtonSize: 30,
                iconSize: 48,
                inset: 16
            )
        ))
        return true
    }
}
Do not hardcode real credentials in source. The host app should use build settings, secret storage, or a local uncommitted file to supply runtime configuration to the SDK.Không hardcode thông tin bảo mật thật trong source. Ứng dụng nên dùng build settings, nơi lưu secret hoặc file local không commit để truyền cấu hình cho SDK.

GtelMapConfiguration referenceTham chiếu GtelMapConfiguration

FieldTrườngDefaultMặc địnhDescriptionMô tả
apiVersion"1.1"API version used in SDK requests. Defaults to "1.1" when not provided.Phiên bản API SDK sử dụng. Mặc định là "1.1" nếu không truyền.
weatherApiKeynilRequired when the host app uses weather features. Supply via GtelMapConfig.configure in AppDelegate.Cần khi ứng dụng dùng tính năng thời tiết. Truyền qua GtelMapConfig.configure trong AppDelegate.
baseURLSDK defaultMặc định SDKOptional environment override provided by the SDK team.Tùy chọn override môi trường do đội SDK cung cấp.
uiGtelMapUIConfiguration.defaultOptional theme for SDK-provided UIKit components: title color and size, subtitle color and size, and component background color.Giao diện tùy chọn cho UIKit component của SDK: màu/cỡ chữ tiêu đề, màu/cỡ chữ phụ và màu nền.
sizeGtelMapSizeConfiguration.defaultOptional sizing for SDK-provided UIKit components: close button size, icon size, and layout inset.Kích thước tùy chọn cho UIKit component của SDK: nút đóng, icon và khoảng cách lề.

GtelMapUIConfiguration referenceTham chiếu GtelMapUIConfiguration

FieldTrườngDefaultMặc địnhDescriptionMô tả
titleColor.blackText color for primary labels in SDK UIKit components.Màu chữ cho nhãn chính trong UIKit component của SDK.
titleSize13Font size for primary labels.Cỡ chữ cho label chính.
subTitleColor.grayText color for secondary/detail labels.Màu chữ cho label phụ/detail.
subTitleSize11Font size for secondary/detail labels.Cỡ chữ cho label phụ/detail.
backgroundColor.whiteBackground color for SDK UIKit component containers, table views, collection views, and reusable cells.Màu nền cho container, table view, collection view và cell dùng lại của UIKit component trong SDK.

GtelMapSizeConfiguration referenceTham chiếu GtelMapSizeConfiguration

FieldTrườngDefaultMặc địnhDescriptionMô tả
closeButtonSize30Width and height for close buttons in SDK UIKit sheets.Chiều rộng và chiều cao của nút đóng trong UIKit sheet của SDK.
iconSize48Size for primary icons in SDK UIKit components.Kích thước icon chính trong UIKit component của SDK.
inset16Leading/trailing content inset used by SDK UIKit components.Khoảng cách trái/phải cho nội dung trong UIKit component của SDK.

Update configuration at runtimeCập nhật cấu hình khi đang chạy

Call apply(configuration:) on an existing GtelMapView instance to apply a new configuration without recreating the view.Gọi apply(configuration:) trên GtelMapView đang có để đổi cấu hình mà không cần tạo lại view.

mapView.apply(configuration: GtelMapConfiguration(baseURL: stagingURL))

Info.plist key & GtelMapConfig helpersKey Info.plist & hàm hỗ trợ GtelMapConfig

Only GTELMapAccessToken is read from Info.plist. All other values (apiVersion, weatherApiKey, baseURL, ui, size) are supplied via GtelMapConfig.configure in AppDelegate.Chỉ GTELMapAccessToken được đọc từ Info.plist. Các giá trị còn lại (apiVersion, weatherApiKey, baseURL, ui, size) được cung cấp qua GtelMapConfig.configure trong AppDelegate.

ConstantHằng sốInfo.plist keyKey Info.plist
GtelMapInfoDictionaryKey.accessTokenGTELMapAccessToken

Use GtelMapConfig static helpers at app launch to guard against missing keys before creating the map view.Dùng các hàm static của GtelMapConfig khi mở app để phòng trường hợp thiếu key trước khi tạo bản đồ.

guard GtelMapConfig.hasAPIKey else {
    fatalError("GTELMapAccessToken missing in Info.plist")
}
GtelMapConfig.configure(GtelMapConfiguration(
    apiVersion: "1.1",
    weatherApiKey: "YOUR_WEATHER_API_KEY",
    ui: .default,
    size: .default
))
HelperHelperDescriptionMô tả
GtelMapConfig.hasAPIKeyReturns true when GTELMapAccessToken is non-empty.Trả true khi GTELMapAccessToken không rỗng.
GtelMapConfig.hasWeatherApiKeyReturns true when weatherApiKey was supplied via GtelMapConfig.configure.Trả true khi weatherApiKey đã được cung cấp qua GtelMapConfig.configure.
GtelMapConfig.apiKeyReads GTELMapAccessToken from main bundle Info.plist.Đọc GTELMapAccessToken từ Info.plist của main bundle.
GtelMapConfig.apiVersionReturns the active API version (configured or SDK default "1.1").Trả API version đang dùng (đã cấu hình hoặc mặc định SDK "1.1").
GtelMapConfig.baseURLReturns the active base URL (overridden or SDK default maps.ots.vn).Trả URL gốc đang dùng (override hoặc mặc định SDK maps.ots.vn).
GtelMapConfig.uiReturns the active UIKit component theme.Trả theme đang áp dụng cho UIKit component của SDK.
GtelMapConfig.sizeReturns the active UIKit component sizing.Trả cấu hình kích thước đang áp dụng cho UIKit component của SDK.
The init(apiKey:weatherApiKey:apiVersion:baseURL:ui:size:) constructor is deprecated. Use init(apiVersion:weatherApiKey:baseURL:ui:size:) instead.Constructor init(apiKey:weatherApiKey:apiVersion:baseURL:ui:size:) đã deprecated. Dùng init(apiVersion:weatherApiKey:baseURL:ui:size:) thay thế.

Map ViewHiển thị bản đồ

Create GtelMapView, assign the delegate, and add it to the layout. All subsequent tasks in this guide assume the host app holds a mapView instance.Tạo GtelMapView, gắn delegate và thêm vào layout. Các phần sau giả định màn hình đã có biến mapView.

final class MapViewController: UIViewController {
    private let mapView = GtelMapView()

    override func viewDidLoad() {
        super.viewDidLoad()
        mapView.gtelMapDelegate = self
        mapView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(mapView)

        NSLayoutConstraint.activate([
            mapView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            mapView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            mapView.topAnchor.constraint(equalTo: view.topAnchor),
            mapView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
    }
}

extension MapViewController: GtelMapViewDelegate {
    func gtelMapViewDidFinishLoading(_ mapView: GtelMapView) {
        mapView.setCameraBoundsInVietNam()
    }
}
GtelMapView initializing the map
Map view before and after the style is ready.Map view trước và sau khi style sẵn sàng.

CameraCamera

The camera is controlled through public helpers on GtelMapView. The host app should store the updated viewport via delegate to use for search, nearby, or UI that depends on the visible map region.Điều khiển camera bằng các hàm public của GtelMapView. Ứng dụng nên lưu vùng bản đồ mới từ delegate để dùng cho tìm kiếm, nearby hoặc giao diện phụ thuộc vị trí đang xem.

APIAPIWhen to useKhi dùng
setCameraZoomToAt(coordinate:edgePadding:completed:)Zoom to a marker, search result, or a host-chosen coordinate.Zoom tới marker, kết quả tìm kiếm hoặc tọa độ do ứng dụng chọn.
setCameraToUserLocation(coordinate:zoomLevel:completed:)Focus the camera on the user's location after the host app has a valid coordinate.Đưa camera tới vị trí người dùng sau khi ứng dụng có tọa độ hợp lệ.
setCameraBoundsInVietNam(completed:)Return to the default viewport when no location is available.Đưa bản đồ về vùng mặc định khi chưa có vị trí.
setCameraDefaultMap(sw:ne:edgePadding:)Fit camera to a custom SW/NE bounds with optional edge padding. Use when the host app has its own bounding box.Căn chỉnh camera vừa vặn vùng bao tọa độ SW/NE do ứng dụng cung cấp (Fit Bounds).
currentZoomLevelKeep the current zoom when changing focus.Giữ mức zoom hiện tại khi đổi vị trí xem.
defaultZoomLevelThe SDK default zoom level (read-only). Use as fallback when currentZoomLevel is not yet available.Mức zoom mặc định của SDK. Dùng khi chưa có currentZoomLevel.
visiableBoundsReturns the current visible bounds (topLeft, bottomRight, center) synchronously without waiting for a delegate callback.Trả vùng bản đồ đang thấy, gồm topLeft, bottomRight và center — trả về ngay, không cần chờ callback delegate.
onSetVisiableBounds(annotations:)Fit the camera to show all annotations.Căn chỉnh camera vừa vặn vùng bao tất cả điểm đánh dấu (Fit to Markers).
onSetVisiableBounds(points:[CLLocationCoordinate2D])Same as above but accepts raw coordinates instead of annotation models.Tương tự, nhưng truyền trực tiếp danh sách tọa độ.
gtelMapView(_:didChangeRegion:)Receive updated bounds after the viewport changes.Nhận vùng bản đồ mới sau khi camera thay đổi.
func focusPlace(_ coordinate: CLLocationCoordinate2D) {
    guard mapView.isValidCoordinate(coordinate) else {
        mapView.setCameraBoundsInVietNam()
        return
    }
    mapView.setCameraZoomToAt(coordinate: coordinate, edgePadding: .zero)
}

func fitCustomBounds(sw: CLLocationCoordinate2D, ne: CLLocationCoordinate2D) {
    mapView.setCameraDefaultMap(sw: sw, ne: ne)
}

func gtelMapView(_ mapView: GtelMapView, didChangeRegion bounds: MapVisibleBounds) {
    currentMapCenter = bounds.center
}

GtelMapCameraChangeReasonGtelMapCameraChangeReason

The regionWillChangeWith and regionDidChangeWith delegate callbacks receive a GtelMapCameraChangeReason OptionSet. Use it to distinguish user gestures from programmatic camera moves.Các callback regionWillChangeWithregionDidChangeWith nhận GtelMapCameraChangeReason. Dùng giá trị này để biết camera đổi do người dùng thao tác hay do code gọi.

CaseTrường hợpMeaningÝ nghĩa
.programmaticCamera moved by an SDK or host app API call.Camera di chuyển do SDK hoặc ứng dụng gọi API.
.gesturePanUser dragged the map.Người dùng kéo bản đồ.
.gesturePinchUser pinched to zoom.Người dùng pinch để zoom.
.gestureZoomIn / .gestureZoomOutDouble-tap or two-finger tap zoom.Chạm hai lần hoặc chạm hai ngón để zoom.
.gestureOneFingerZoomOne-finger drag zoom gesture.Drag một ngón để zoom.
.gestureTiltTwo-finger vertical drag to tilt.Kéo dọc bằng hai ngón để nghiêng bản đồ.
.transitionCancelledA programmatic animation was interrupted.Animation programmatic bị ngắt giữa chừng.
func gtelMapView(_ mapView: GtelMapView, regionDidChangeWith reason: GtelMapCameraChangeReason, animated: Bool) {
    if reason.contains(.gesturePan) || reason.contains(.gesturePinch) {
        dismissSearchPanel()
    }
}

Style & LayerStyle & lớp

The host app reads the style catalog and applies the item the user selects via GtelMapViewInput.Ứng dụng lấy danh sách style, áp dụng style người dùng chọn qua GtelMapViewInput.

func loadStyles() {
    // Option A: read the local catalog synchronously
    styleItems = GtelMapClient.shared.mapStyles

    // Option B: receive it via the delegate through GtelMapViewInput
    mapView.apply(input: .mapStyles)
}

func applyStyle(_ style: GtelMapStyleModel) {
    mapView.apply(input: .mapStyle(style))
}

func applyExternalStyle(_ source: GtelMapStyleSource) {
    mapView.apply(input: .mapStyleSource(source))
}

Built-in styles (GtelMapStyle)Style dựng sẵn (GtelMapStyle)

Switch a built-in style with mapView.apply(style:). Existing markers and routes re-attach once the new style has loaded.Đổi style dựng sẵn bằng mapView.apply(style:). Marker và tuyến đường hiện có sẽ tự gắn lại sau khi style mới tải xong.

// Create the map already set to a built-in style
let mapView = GtelMapView(style: .STREETS)

// Or switch style at any time
mapView.apply(style: .STREETS)

// Resolve a style from a raw id (nil for an unknown id)
if let style = GtelMapStyle.fromId("dark") {
    mapView.apply(style: style)
}
GtelMapStyleGtelMapStyleGtelMapStyleGtelMapStyle
.STREETS.BASIC.LIGHT.DARK
.SATELLITE.SATELLITE_STREETS.NAVIGATION_DAY.NAVIGATION_NIGHT
.ONLY_TRAFFIC.ONLY_TRAFFIC_DARK
Each GtelMapStyle exposes styleId (e.g. gtelmaps-streets-v1) and model (a GtelMapStyleModel). Use .mapStyle(GtelMapStyleModel) for catalog items and .mapStyleSource(_:) for external styles.Mỗi GtelMapStyle cung cấp styleId (vd gtelmaps-streets-v1) và model (một GtelMapStyleModel). Dùng .mapStyle(GtelMapStyleModel) cho style trong danh sách và .mapStyleSource(_:) cho style bên ngoài.

Custom style contentCustom style content

Use custom style content when the host app already has GeoJSON-like content, images, layer ids, or filters to control on the current style.Dùng custom style content khi ứng dụng đã có dữ liệu dạng GeoJSON, hình ảnh, layer id hoặc bộ lọc cần hiển thị trên style hiện tại.

All custom content ids, source ids, layer ids, and image names must start with host_ to avoid collisions with SDK-internal identifiers.Tất cả content id, source id, layer id và tên hình do ứng dụng đặt phải bắt đầu bằng host_ để tránh trùng với id nội bộ của SDK.
InputInputDescriptionMô tả
.customStyleImage(name:image:), .removeCustomStyleImage(name:)Register or remove reusable images for custom style layers.Thêm hoặc xóa hình dùng cho layer tùy chỉnh.
.customStyleContent(content:)Add a new GtelMapCustomStyleContent (sources + layers + features). Use once per content id; update individual features with granular inputs.Thêm một GtelMapCustomStyleContent. Mỗi content id chỉ thêm một lần; khi dữ liệu đổi thì cập nhật từng feature.
.updateCustomStyleSource(contentId:source:)Replace all features in an existing source without removing the whole content block.Thay toàn bộ feature trong source đã có mà không xóa cả content.
.updateCustomStyleFeature(contentId:sourceId:feature:)Update a single feature by id within an existing source.Cập nhật một feature theo id.
.removeCustomStyleFeature(contentId:sourceId:featureId:)Remove a single feature by id from an existing source.Xóa một feature theo id.
.removeCustomStyleContentById(contentId:)Remove an entire content block (all its sources, layers, and features) by content id.Xóa toàn bộ content theo content id.
.removeCustomStyleContent(layerIds:sourceIds:)Remove specific layers and sources by id lists.Xóa layer và source theo danh sách id.
.clearCustomStyleContentRemove all host-owned custom content at once.Xóa toàn bộ custom content của ứng dụng.
.setCustomStyleLayerVisibility(layerIds:isVisible:)Show or hide custom layers by id list.Bật hoặc tắt layer theo danh sách id.
.setCustomStyleLayerFilter(layerId:propertyKey:allowedValues:), .clearCustomStyleLayerFilter(layerId:)Filter visible features by a property value list, or clear the filter.Lọc feature được hiển thị theo giá trị, hoặc xóa bộ lọc.

Custom style typesCác type của custom style

GtelMapCustomLayerKind

.symbol · .circle · .line · .fill

GtelMapCustomLayerPosition

.top · .above(layerId) · .below(layerId)

GtelMapCustomLayerStyle controls visual appearance. Key fields: color, strokeColor, opacity, width (line), radius (circle), iconScale (symbol), showsTitle, allowsOverlap.GtelMapCustomLayerStyle điều khiển cách layer hiển thị. Các trường thường dùng gồm color, strokeColor, opacity, width, radius, iconScale, showsTitleallowsOverlap.

Read-back helpersHàm đọc trạng thái

Use these to inspect the current custom style state without tracking it separately in the host app.Dùng các hàm này để kiểm tra custom style hiện tại mà ứng dụng không cần tự lưu thêm.

Property / MethodThuộc tính / Phương thứcReturnsKiểu trả về
customStyleContentIds[String] — all active content ids.— tất cả content id đang active.
customStyleLayerIds[String] — all active custom layer ids.— tất cả custom layer id đang active.
customStyleSourceIds[String] — all active custom source ids.— tất cả custom source id đang active.
customStyleImageNames[String] — registered custom image names.— tên image custom đã đăng ký.
customStyleFilters[GtelMapCustomLayerFilter] — active layer filters.— filter layer đang active.
customStyleContent(id:)GtelMapCustomStyleContent?
customStyleSource(contentId:sourceId:)GtelMapCustomSource?
customStyleFeature(contentId:sourceId:featureId:)GtelMapCustomFeature?
customStyleFeatures(contentId:sourceId:where:)[GtelMapCustomFeature] — filtered by predicate.— lọc theo predicate.
visibleCustomStyleFeatures()[GtelMapCustomFeature] — features currently visible on screen.— các feature đang hiển thị trên màn hình.

Custom feature tapTap vào custom feature

When the user taps a feature in a host-owned custom layer, the SDK fires didTapCustomFeature. The layerId parameter identifies which layer was tapped.Khi người dùng chạm vào feature trong custom layer của ứng dụng, SDK gọi didTapCustomFeature. Tham số layerId cho biết layer nào được chạm.

func gtelMapView(_ mapView: GtelMapView, didTapCustomFeature feature: GtelMapCustomFeature, layerId: String?) {
    guard let id = feature.id else { return }
    showDetail(for: id, layer: layerId)
}

Custom style errorsLỗi custom style

The delegate has two didFailCustomStyleContent overloads: one with ResponseMessage (network/general) and one with typed GtelMapCustomStyleContentError (validation). Common validation errors:Delegate có hai hàm didFailCustomStyleContent: một hàm trả ResponseMessage cho lỗi chung, một hàm trả GtelMapCustomStyleContentError cho lỗi dữ liệu đầu vào. Các lỗi thường gặp:

ErrorLỗiCauseNguyên nhân
.invalidSourceId / .invalidLayerId / .invalidImageNameId or name does not start with host_.Id hoặc name không bắt đầu bằng host_.
.duplicateSourceId / .duplicateLayerIdTwo sources or layers with the same id in one content block.Hai source hoặc layer có cùng id trong một content block.
.missingLayerSourceA layer references a source id not declared in the same content block.Layer tham chiếu source id chưa khai báo trong cùng content block.
.rendererNotReadyMap style is not yet loaded. Wait for gtelMapViewDidFinishLoading before adding custom content.Style bản đồ chưa tải xong. Chờ gtelMapViewDidFinishLoading rồi mới thêm custom content.
Default map style
Default.
Satellite map style
Satellite.
Hybrid map style
Hybrid.

Marker & CalloutMarker & Callout

The host app creates an AnnotationModel and renders a single marker or multiple annotations. Icons, annotation views, and callouts are customised via the delegate.Ứng dụng tạo AnnotationModel để hiển thị một hoặc nhiều marker. Icon, view marker và callout được tùy biến qua delegate.

func showFocusedMarker(_ annotation: AnnotationModel) {
    mapView.apply(input: .marker(annotation, iconScale: 1.0, zoomLevel: 16))
}

func showMarkers(_ annotations: [AnnotationModel]) {
    mapView.apply(input: .annotations(annotations, layerId: "places", visibleLayerIds: ["places"], iconScale: 1.0))
}

func clearMarkers() {
    mapView.removeAllAnnotations()
    mapView.deselectAllCallout()
}

func gtelMapView(_ mapView: GtelMapView, didTouchAnnotation annotation: AnnotationModel) {
    selectedAnnotation = annotation
}

func gtelMapView(_ mapView: GtelMapView, markerImageFor annotation: AnnotationModel) -> UIImage? {
    markerIcon(for: annotation)
}

Custom annotation viewView annotation tùy chỉnh

Return a UIView from annotationViewFor to render a fully custom annotation instead of an icon image. The view is pinned to the annotation coordinate.Trả UIView từ annotationViewFor để hiển thị marker tùy chỉnh thay vì chỉ dùng icon. View sẽ được đặt tại tọa độ của marker.

func gtelMapView(_ mapView: GtelMapView, annotationViewFor annotation: AnnotationModel) -> UIView? {
    guard annotation.type == "highlight" else { return nil }
    let badge = PulsingBadgeView()
    badge.tintColor = .systemRed
    return badge
}

Callout lifecycleVòng đời hiển thị của khung bóng thoại thông tin (Callout View) (Callout Lifecycle)

Callback / HelperCallback / HelperDescriptionMô tả
canShowCalloutForReturn whether an annotation should open a callout.Quyết định annotation có được mở callout hay không.
leftCalloutAccessoryViewFor, rightCalloutAccessoryViewForProvide host-owned callout accessory views.Cung cấp view phụ trong callout do ứng dụng tự tạo.
didShowCalloutFired when callout becomes visible. isLoadingSubtitle is true while the SDK is resolving the subtitle asynchronously.Được gọi khi callout hiển thị. isLoadingSubtitletrue khi SDK đang tải subtitle.
didUpdateCalloutSubtitleFired when the subtitle string is resolved. Update the host preview panel to show the address.Được gọi khi đã có subtitle. Cập nhật phần xem trước để hiển thị địa chỉ.
didUpdateCalloutCategoryFired when the SDK resolves the place category type string (e.g. "restaurant"). Use to update the category icon in the callout.Được gọi khi đã có loại địa điểm. Dùng để cập nhật icon trong callout.
gtelMapViewDidRemoveCalloutFired when the callout is dismissed. Use to reset host preview panels.Được gọi khi callout đóng. Dùng để reset phần xem trước.
deselectAllCallout(), removeAllAnnotations()Clear selected callout or all annotations when leaving the flow.Xóa callout đang chọn hoặc toàn bộ marker khi rời màn hình.

Callout positioning helpersHàm căn chỉnh callout

When the host app places a custom overlay anchored to the callout (e.g. a bottom sheet pinned above it), use these helpers to keep it aligned after layout changes.Khi ứng dụng đặt một overlay gắn với callout, ví dụ bottom sheet nằm phía trên callout, dùng các hàm này để giữ đúng vị trí sau khi layout thay đổi.

APIAPIDescriptionMô tả
calloutAnchorPoint(for:)Returns the anchor CGPoint in the GtelMapView coordinate space for a given annotation. Returns nil if the annotation is not visible.Trả CGPoint của marker trong GtelMapView. Trả nil nếu marker không hiển thị.
scheduleOverlayPositionUpdate(notifiesCalloutPositionUpdate:animated:)Ask the SDK to recalculate overlay positions. Set notifiesCalloutPositionUpdate: true to trigger didRequestCalloutPositionUpdate on the delegate.Yêu cầu SDK tính lại vị trí overlay. Đặt notifiesCalloutPositionUpdate: true để gọi didRequestCalloutPositionUpdate trên delegate.
didRequestCalloutPositionUpdate(animated:)Delegate callback to reposition host-owned views aligned to the callout.Callback để ứng dụng đặt lại vị trí các view gắn với callout.
Android documents automatic clustering. This iOS public guide does not document clustering until it is exposed through GtelMapView public API.Android có mục clustering tự động. iOS guide public chưa document clustering cho tới khi tính năng này được expose qua public API của GtelMapView.
Marker rendered on the map
Marker.
Selected marker on the map
Selected marker.
Custom callout
Custom callout.

RouteVẽ tuyến

A route can be loaded via a navigation input or rendered from a RouteResponseModel the host app already received via delegate.Có thể tải tuyến đường bằng navigation input, hoặc hiển thị từ RouteResponseModel mà ứng dụng đã nhận qua delegate.

func requestRoute(from origin: LocationDataRequest, to destination: LocationDataRequest, costing: TransportType) {
    mapView.apply(input: .navigationRoute(locations: [origin, destination], costing: costing))
}

func renderRoute(_ response: RouteResponseModel) {
    mapView.apply(input: .route(response))
}

func clearRoute() {
    mapView.apply(input: .clearRoute)
}

func gtelMapView(_ mapView: GtelMapView, didLoadNavigationRoute route: RouteResponseModel, selectedTrip: TripModel?) {
    routeSummary = selectedTrip
}

Alternative and candidate routesTuyến đường thay thế và các tuyến đề xuất (Alternative & Candidate Routes)

For A/B alternatives, request the candidate route data through the host flow, then render the public response set with .matrixCandidateRoutes. Use delegate route-selection callbacks to keep host UI in sync.Với nhiều tuyến thay thế, ứng dụng lấy dữ liệu tuyến trước, rồi hiển thị bằng .matrixCandidateRoutes. Dùng callback chọn tuyến để cập nhật giao diện.

func renderCandidateRoutes(_ routes: [RouteResponseModel?], colors: [UIColor], sources: [MatrixRouteSourceMarker], targets: [MatrixRouteTargetMarker]) {
    mapView.apply(input: .matrixCandidateRoutes(
        responses: routes,
        colors: colors,
        sourceMarkers: sources,
        targetMarkers: targets,
        optimalIndex: 0,
        optimalTargetIndex: 0
    ))
}

func gtelMapView(_ mapView: GtelMapView, didSelectNavigationRoute route: RouteResponseModel, selectedTrip: TripModel?) {
    selectedRoute = route
}
Route line rendered on the map
Route line rendered through the map view's public input.Đường tuyến được hiển thị qua input public của map view.

Direct route API helpersHàm lấy dữ liệu tuyến đường

Use these when the host app needs route data without rendering it on the map (e.g. to display a distance summary before the user confirms).Dùng khi ứng dụng cần dữ liệu tuyến đường nhưng chưa cần hiển thị lên bản đồ, ví dụ để xem trước khoảng cách trước khi người dùng xác nhận.

MethodPhương thứcUse caseTrường hợp sử dụng
GtelMapClient.shared.getRoutes(request:callback:)Fetch a route response without rendering. Returns RouteResponseModel? via callback. Ideal for showing ETA before starting navigation.Lấy tuyến đường mà chưa hiển thị lên bản đồ. Trả RouteResponseModel? qua callback. Phù hợp để hiển thị ETA trước khi dẫn đường.
GtelMapClient.shared.getDoorToDoorRoute(request:callback:)Fetch a door-to-door route (includes last-mile walking segments). Returns RouteResponseModel? via callback.Định tuyến điểm đầu - điểm cuối toàn diện (Door-to-Door Routing), tự động bổ sung đoạn đi bộ kết nối. Trả RouteResponseModel? qua callback.
let req = EstimateTimeDataRequest(
    origin: LocationDataRequest(lat: 10.776, lng: 106.701, address: "Point A"),
    destination: LocationDataRequest(lat: 10.800, lng: 106.720, address: "Point B"),
    costing: .auto
)
GtelMapClient.shared.getRoutes(request: req) { response, message in
    guard message.onCheckSuccess(), let trip = response?.trip else { return }
    showSummary(distance: trip.summary?.length, time: trip.summary?.time)
}

GtelMapClient.shared.getDoorToDoorRoute(request: req) { response, message in
    guard message.onCheckSuccess() else { return }
    renderDoorToDoorResult(response)
}

Overlay (boundary)Lớp phủ (ranh giới)

Use polygon or custom style content when the host app has region data to display. This guide does not describe backend details for generating region data.Dùng polygon hoặc custom style content khi ứng dụng có sẵn dữ liệu vùng cần hiển thị. Guide không mô tả chi tiết hệ thống tạo dữ liệu vùng.

func showBoundary(_ coordinates: [CLLocationCoordinate2D]) {
    guard coordinates.count >= 3 else { return }
    mapView.apply(input: .polygon(coordinates: coordinates))
}

func clearBoundary() {
    mapView.apply(input: .clearPolygon)
}
Administrative boundary polygon
Boundary polygon.
Province-level boundary
Province.
Ward-level boundary
Ward.

Map EventsSự kiện bản đồ

Map events flow through GtelMapViewDelegate. The host app only implements the callbacks it needs; all callbacks have empty default implementations.Sự kiện bản đồ được gửi qua GtelMapViewDelegate. Ứng dụng chỉ cần cài đặt các callback đang dùng; callback còn lại đã có mặc định rỗng.

CallbackCallbackWhen firedKhi kích hoạt
gtelMapViewDidFinishLoading(_:)Map is fully initialized and ready for inputs. Send first actions here.Bản đồ đã sẵn sàng nhận input. Gửi lệnh đầu tiên tại đây.
gtelMapViewDidFinishLoadingStyle(_:)Fired every time a style finishes loading, including after .mapStyle / .mapStyleSource switches. Re-apply host-owned custom style content here if needed.Được gọi mỗi khi style tải xong, kể cả sau khi đổi style. Nếu cần giữ custom style content, hãy gửi lại tại đây.
gtelMapViewRegionIsChanging(_:)Fires continuously while the camera is in motion. Use sparingly — avoid expensive UI updates here.Được gọi liên tục khi camera đang di chuyển. Chỉ nên cập nhật giao diện nhẹ tại đây.
regionWillChangeWith(reason:animated:)Camera is about to move. reason is a GtelMapCameraChangeReason OptionSet.Camera sắp di chuyển. reasonGtelMapCameraChangeReason OptionSet.
regionDidChangeWith(reason:animated:)Camera finished moving.Camera đã dừng.
didChangeRegion(bounds:)Returns the new MapVisibleBounds (topLeft, bottomRight, center). Store bounds.center for search focus.Trả MapVisibleBounds mới. Lưu bounds.center để ưu tiên tìm kiếm quanh khu vực đang xem.
didTapCoordinate(_:coordinate:)User tapped an empty area of the map (no annotation or POI).Người dùng chạm vào vùng trống trên bản đồ.
didPinCoordinate(_:coordinate:)User long-pressed the map. Typically trigger a .reversePoint input here.Người dùng nhấn giữ trên bản đồ. Thường gửi .reversePoint tại đây.
gtelMapViewDidBeginGesturePan / gtelMapViewDidEndGesturePanPan gesture started or ended. Use to show/hide search bar or floating UI.Người dùng bắt đầu hoặc dừng kéo bản đồ. Có thể dùng để ẩn/hiện thanh tìm kiếm.
extension MapViewController: GtelMapViewDelegate {
    func gtelMapViewDidFinishLoadingStyle(_ mapView: GtelMapView) {
        // re-apply custom content after each style reload
        if let content = pendingCustomContent {
            mapView.apply(input: .customStyleContent(content: content))
        }
    }

    func gtelMapViewRegionIsChanging(_ mapView: GtelMapView) {
        // lightweight: update a loading indicator only
        mapView.scheduleOverlayPositionUpdate()
    }

    func gtelMapView(_ mapView: GtelMapView, didTapCoordinate coordinate: CLLocationCoordinate2D) {
        tappedCoordinate = coordinate
    }

    func gtelMapView(_ mapView: GtelMapView, didPinCoordinate coordinate: CLLocationCoordinate2D) {
        mapView.apply(input: .reversePoint(coordinate: coordinate, showMarker: true, zoom: 18, size: 1))
    }

    func gtelMapView(_ mapView: GtelMapView, regionWillChangeWith reason: GtelMapCameraChangeReason, animated: Bool) {
        if reason.contains(.gesturePan) { dismissSearchPanel() }
    }

    func gtelMapView(_ mapView: GtelMapView, regionDidChangeWith reason: GtelMapCameraChangeReason, animated: Bool) {}

    func gtelMapViewDidBeginGesturePan(_ mapView: GtelMapView) {}

    func gtelMapViewDidEndGesturePan(_ mapView: GtelMapView) {}
}

User LocationVị trí người dùng

The host app is responsible for requesting location permission and obtaining coordinates via CLLocationManager. Once a valid coordinate is available, pass it to the camera helper on GtelMapView.Ứng dụng tự xin quyền vị trí và lấy tọa độ bằng CLLocationManager. Sau khi có tọa độ hợp lệ, truyền vào hàm camera của GtelMapView.

func handleLocation(_ coordinate: CLLocationCoordinate2D?) {
    guard let coordinate, mapView.isValidCoordinate(coordinate) else {
        mapView.setCameraBoundsInVietNam()
        return
    }

    mapView.setCameraToUserLocation(coordinate: coordinate, zoomLevel: mapView.currentZoomLevel)
    mapView.showUserCurrentLocation()
}
Do not call the current location flow if the host app has no permission or a valid coordinate. On the Simulator, verify the simulated location before debugging camera behavior.Không gọi luồng vị trí hiện tại nếu ứng dụng chưa có quyền hoặc chưa có tọa độ hợp lệ. Với Simulator, kiểm tra vị trí giả lập trước khi debug camera.
User location shown on the map
Current location after the host app provides a valid coordinate.Vị trí hiện tại sau khi ứng dụng truyền tọa độ hợp lệ.

POI InteractionTương tác POI trên bản đồ

When the user taps a built-in map POI (restaurants, fuel stations, hospitals, etc.), the SDK automatically shows a callout and loads place details. The host app receives data through delegate callbacks and can respond to callout button taps via public helpers.Khi người dùng chạm vào POI có sẵn trên bản đồ như nhà hàng, trạm xăng hoặc bệnh viện, SDK tự hiển thị callout và tải chi tiết địa điểm. Ứng dụng nhận dữ liệu qua delegate callback và xử lý nút trong callout bằng các hàm public.

POI delegate flowLuồng delegate của POI

CallbackCallbackWhen firedKhi kích hoạt
didTouchAnnotation(_:annotation:)Fired immediately when the user taps any annotation or POI. Provides the initial AnnotationModel with title and category.Được gọi ngay khi người dùng chạm vào marker hoặc POI. Trả AnnotationModel ban đầu gồm tiêu đề và loại địa điểm.
didShowCallout(_:annotation:isLoadingSubtitle:)Fired when the callout bubble appears. isLoadingSubtitle: true means the address is still resolving.Được gọi khi callout xuất hiện. isLoadingSubtitle: true nghĩa là địa chỉ vẫn đang tải.
didRequestPlaceDetail(_:placeId:)Fired before the SDK fetches POI detail. Useful for pre-loading UI or showing a skeleton screen.Được gọi trước khi SDK lấy chi tiết POI. Có thể dùng để hiển thị trạng thái đang tải.
didUpdateCalloutSubtitle(_:subtitle:)Fired when the resolved address string is available. Update the callout or bottom sheet subtitle here.Được gọi khi đã có địa chỉ. Cập nhật subtitle của callout hoặc bottom sheet tại đây.
didUpdateCalloutCategory(_:type:)Fired when the SDK resolves the place category string (e.g. "restaurant"). Update the category icon here.Được gọi khi đã có loại địa điểm. Cập nhật icon loại địa điểm tại đây.
didLoadPOIDetail(_:detail:PlaceDetailModel)Fired when full PlaceDetailModel is available (name, address, phone, types, hours, etc.). Populate a detail bottom sheet.Được gọi khi đã có PlaceDetailModel đầy đủ như tên, địa chỉ, số điện thoại, loại địa điểm và giờ mở cửa.
gtelMapViewDidRemoveCallout(_:)Fired when the callout is dismissed. Reset the host preview panel.Được gọi khi callout đóng. Dùng để reset phần xem trước của ứng dụng.

POI callout action helpersHelpers xử lý action của POI callout

When the host app renders a custom button inside the callout (e.g. "Navigate" or "Call"), call these helpers so the SDK coordinates the internal state properly.Khi ứng dụng hiển thị nút riêng trong callout, ví dụ "Dẫn đường" hoặc "Gọi", hãy gọi các hàm này để SDK cập nhật trạng thái đúng.

// User tapped the primary action button in the POI callout
func userDidTapCalloutPrimary() {
    mapView.handlePOICalloutTap()
}

// User tapped the direction button in the POI callout
func userDidTapCalloutDirection() {
    mapView.handlePOICalloutDirection()
}

PlaceDetailModelPlaceDetailModel

PlaceDetailModel returned in didLoadPOIDetail is the same model used by the .placeDetail input flow. Key fields:PlaceDetailModel nhận được trong didLoadPOIDetail là cùng model với input .placeDetail. Các trường chính:

FieldTrườngDescriptionMô tả
nameDisplay name of the place.Tên hiển thị của địa điểm.
formattedAddress / adrFormatAddressFull address string. Prefer adrFormatAddress when available.Chuỗi địa chỉ đầy đủ. Ưu tiên adrFormatAddress khi có.
types[CatetoryPlaceType]place category list.danh sách loại địa điểm.
internationalPhoneNumberPhone number for the "Call" action.Số điện thoại cho chức năng gọi điện.
The difference between didLoadPOIDetail and didLoadPlaceDetail: the first is fired automatically when the user taps a map POI; the second is fired when the host app explicitly sends .placeDetail(placeId) input.Phân biệt didLoadPOIDetaildidLoadPlaceDetail: didLoadPOIDetail tự chạy khi người dùng chạm POI trên bản đồ; didLoadPlaceDetail chạy khi ứng dụng gửi input .placeDetail(placeId).

Turn-by-turn UIDẫn đường từng ngã rẽ (Turn-by-turn)

GtelRouteNavigationViewController is a fully self-contained navigation UI. The host app initializes it with a list of stop coordinates, then presents it modally or pushes it onto a navigation stack. The SDK handles map rendering, turn instructions, voice guidance, and summary panels internally.GtelRouteNavigationViewController là giao diện dẫn đường hoàn chỉnh. Ứng dụng truyền danh sách tọa độ điểm dừng/điểm trung chuyển (Waypoint), sau đó present modal hoặc push vào navigation stack. SDK tự hiển thị bản đồ, hướng dẫn rẽ, giọng nói và bảng tóm tắt hành trình.

Class GtelRouteNavigationViewController Mode .live · .demo Base UIViewController
let navVC = GtelRouteNavigationViewController(
    stops: [originCoordinate, destinationCoordinate],
    profile: .car,          // GtelRouteNavigationProfile
    language: "vi",         // instruction language
    mode: .live             // .live (real GPS) or .demo (simulated)
)
present(navVC, animated: true)
ParameterTham sốTypeKiểu dữ liệuDescriptionMô tả
stops[CLLocationCoordinate2D]Ordered list of waypoints. Minimum two: origin and destination.Danh sách waypoint theo thứ tự. Tối thiểu hai điểm: xuất phát và đích.
profileGtelRouteNavigationProfileTransport profile (e.g. .car, .bike, .foot).Profile phương tiện (ví dụ .car, .bike, .foot).
languageStringBCP-47 language code for spoken and on-screen instructions. Use "vi" for Vietnamese.Mã ngôn ngữ BCP-47 cho hướng dẫn nói và hiển thị. Dùng "vi" cho tiếng Việt.
modeGtelRouteNavigationMode.live uses the device GPS; .demo simulates movement along the route — useful for testing without driving..live dùng GPS thật của thiết bị; .demo giả lập di chuyển dọc route — hữu ích khi test mà không cần lái xe.

Host apps should treat GtelRouteNavigationViewController as the navigation boundary. Provide stops, profile, language, and mode when initializing the controller; the SDK loads the route and manages the turn-by-turn runtime internally.Ứng dụng chỉ cần làm việc với GtelRouteNavigationViewController khi dùng dẫn đường. Truyền stops, profile, language và mode khi khởi tạo; SDK tự tải tuyến và quản lý dẫn đường từng ngã rẽ (Turn-by-turn).

SurfaceSurfaceHost usageCách ứng dụng dùng
GtelRouteNavigationViewControllerCreate and present/push the full navigation UI.Khởi tạo và present/push UI dẫn đường hoàn chỉnh.
GtelRouteNavigationProfileChoose .car, .bike, or .foot.Chọn .car, .bike hoặc .foot.
GtelRouteNavigationModeUse .live for GPS navigation or .demo for simulated movement.Dùng .live cho GPS thật hoặc .demo để giả lập di chuyển.

Road · OtherĐường · dịch vụ khác

A group of auxiliary tasks corresponding to Android Road · Other: snap to roads, matrix route, isochrone, geofencing, weather, and static map. Use GtelMapClient.shared for data-only calls and GtelMapView.apply(input:) when the result must be rendered on the map.Nhóm tính năng phụ gồm snap to roads, matrix route, isochrone, geofencing, weather và static map. Dùng GtelMapClient.shared khi chỉ cần lấy dữ liệu; dùng GtelMapView.apply(input:) khi cần hiển thị kết quả lên bản đồ.

Snap to roads

GtelMapClient.shared.snapToRoads, .snapToRoads, .snapToRoadsPlayback, .clearSnapToRoads.

Matrix route

.matrixRoute to request a matrix and .matrixCandidateRoutes to render candidate routes..matrixRoute để yêu cầu ma trận tuyến và .matrixCandidateRoutes để hiển thị các tuyến đề xuất.

Isochrone

GtelMapClient.shared.isochrone, .isochrone, .clearIsochrone.

Geofencing

.geofencingPolygon, callbacks didLoadGeofencingResult and didFailGeofencing..geofencingPolygon trả kết quả qua didLoadGeofencingResult và lỗi qua didFailGeofencing.

Weather

GtelMapClient.shared.getWeather for the host app to show its own weather UI.GtelMapClient.shared.getWeather giúp ứng dụng hiển thị giao diện thời tiết riêng.

Static Map

GtelMapClient.shared.getStaticMap returns a UIImage for preview/thumbnails.GtelMapClient.shared.getStaticMap trả UIImage cho preview/thumbnail.

func loadStaticPreview(center: CLLocationCoordinate2D) {
    let request = StaticMapRequest(
        center: center,
        zoom: 14,
        size: StaticMapSize(width: 640, height: 360)
    )

    GtelMapClient.shared.getStaticMap(request: request) { image, message in
        guard message.onCheckSuccess(), let image else { return }
        previewImageView.image = image
    }
}

func checkFence(pointId: String, coordinate: CLLocationCoordinate2D, geometry: PolygonGeometryModel) {
    mapView.apply(input: .geofencingPolygon(pointId: pointId, coordinate: coordinate, geometry: geometry))
}

Service referenceTham khảo service public

CapabilityUse throughResult path
Snap to roadsGtelMapClient.shared.snapToRoads or .snapToRoadsCallback response or map-rendered snapped route.Nhận kết quả qua callback hoặc hiển thị tuyến đã khớp đường trên bản đồ.
IsochroneGtelMapClient.shared.isochrone then .isochroneCallback response, then public input for map overlay.Nhận kết quả qua callback, sau đó dùng input public để hiển thị lớp phủ.
Geofencing.geofencingPolygondidLoadGeofencingResult, didFailGeofencing
WeatherGtelMapClient.shared.getWeatherCallback returns data for host-owned UI.Callback trả dữ liệu cho giao diện do ứng dụng quản lý.
Static mapGtelMapClient.shared.getStaticMapCallback returns a preview UIImage.Callback trả ảnh preview dạng UIImage.

UIKit ComponentsUIKit Components public

The SDK includes native UIKit components for common host UI flows. These components do not replace GtelMapView; the host app still applies map changes through GtelMapView.apply(input:) and handles selected data through closures or delegates.SDK cung cấp một số UIKit component cho các giao diện phổ biến. Các component này không thay thế GtelMapView; ứng dụng vẫn gửi thay đổi lên bản đồ bằng GtelMapView.apply(input:) và nhận lựa chọn của người dùng qua closure hoặc delegate.

ComponentComponentInputInputCallbackCallback
GtelPlaceSearchViewControllerInitial text and optional center coordinate.Text ban đầu và tọa độ trung tâm nếu có.Selected place model.Model địa điểm được chọn.
GtelMapStylePickerViewController[GtelMapStyleModel], selectedStyleonSelect or GtelMapStylePickerDelegate
GtelNearbyCategoryView[CatetoryPlaceType]onSelect or GtelNearbyCategoryViewDelegate
GtelWeatherBottomSheetViewControllerWeatherResponseModelonClose or GtelWeatherBottomSheetDelegate
GtelRouteDirectionViewControllerRoute summary, transport modes, maneuvers.Route summary, danh sách transport mode và maneuver.GtelRouteDirectionDelegate
GtelMultiStopPointViewController[MultiStopPointItem]GtelMultiStopPointDelegate
// The style catalog is served locally by the SDK — no network call needed
let mapStyles = GtelMapClient.shared.mapStyles

let picker = GtelMapStylePickerViewController(items: mapStyles, selectedStyle: currentStyle)
picker.onSelect = { [weak self, weak picker] style in
    picker?.dismiss(animated: true)
    self?.mapView.apply(input: .mapStyle(style))
}
present(picker, animated: true)
let categoryView = GtelNearbyCategoryView()
categoryView.onSelect = { [weak self] category in
    self?.mapView.apply(input: .nearbySearch(category: category, location: center))
}
Keep business rules, permission prompts, network retry policy, and map rendering decisions in the host app. SDK UI components only package the reusable visual layer and selection callbacks.Ứng dụng vẫn tự quản lý business rule, xin quyền, retry khi lỗi mạng và quyết định có hiển thị lên bản đồ hay không. SDK UI component chỉ cung cấp giao diện tái sử dụng và callback khi người dùng thao tác.

GtelMapClient — Independent ServicesGtelMapClient — Service độc lập

GtelMapClient.shared is the public service facade for host-owned UI and background workflows that do not need a GtelMapView instance. Configure the SDK once with GtelMapConfig.configure before the first service call.GtelMapClient.shared dùng để lấy dữ liệu cho giao diện riêng hoặc xử lý nền khi không cần GtelMapView. Cấu hình SDK một lần bằng GtelMapConfig.configure trước lần gọi đầu tiên.

Use GtelMapClient to fetch data. Use GtelMapView.apply(input:) to render data on the map. Use GtelMapViewDelegate to receive map events and map-render callbacks.Dùng GtelMapClient để lấy dữ liệu. Dùng GtelMapView.apply(input:) để hiển thị dữ liệu lên bản đồ. Dùng GtelMapViewDelegate để nhận sự kiện bản đồ và callback hiển thị.

SetupCấu hình

import GtelMapSDK

GtelMapConfig.configure(GtelMapConfiguration(
    apiVersion: "1.1",
    weatherApiKey: "YOUR_WEATHER_API_KEY"
))

GtelMapClient.shared.reversePoint(
    pointLat: 21.0278,
    pointLon: 105.8342
) { place, message in
    guard message.onCheckSuccess(), let place else { return }

    showAddress(place)
}

Choose the right entry pointChọn đúng entry point

Use caseUse caseUseDùng
Read the built-in map style catalog for a custom style picker (served locally, no network call).Lấy danh sách style dựng sẵn cho bộ chọn style riêng (trả về cục bộ, không gọi mạng).GtelMapClient.shared.mapStyles
Load autocomplete or geocoding results for a custom list UI.Lấy kết quả autocomplete hoặc geocoding cho danh sách riêng.GtelMapClient.shared
Calculate route, matrix, weather, static map, snap to roads, isochrone, or geofencing result outside a live map screen.Tính tuyến đường, matrix, thời tiết, static map, snap to roads, isochrone hoặc geofencing ngoài màn hình bản đồ.GtelMapClient.shared
Render markers, route polylines, polygons, isochrone zones, or snapped roads on the map.Hiển thị marker, tuyến đường, polygon, vùng isochrone hoặc snap road lên bản đồ.GtelMapView.apply(input:)
React to map gestures, marker taps, POI taps, and map-render lifecycle events.Nhận thao tác kéo/chạm bản đồ, marker, POI và sự kiện hiển thị bản đồ.GtelMapViewDelegate

Available service methodsCác service method hiện có

GroupNhómMethodsMethodTypical host useCách dùng thường gặp
GeocodingreversePoint, autocomplete, forwardGeocoding, getLocationDetail, getMatrixRouteSearch, address forms, place detail screens, ETA tables.Search, form địa chỉ, màn chi tiết địa điểm, bảng ETA.
PlacesnearbySearchFind places of a given type around a location for a host-owned list or picker.Tìm địa điểm theo loại quanh một vị trí cho danh sách hoặc bộ chọn riêng.
Map stylesmapStylesRead the local built-in style catalog to build a host-owned style switcher (no network call).Lấy danh sách style dựng sẵn cục bộ để ứng dụng tự làm bộ đổi style (không gọi mạng).
AdministrativegetProvincePolygon, getWardPolygonLoad administrative boundaries before rendering or checking a region.Lấy ranh giới hành chính trước khi hiển thị hoặc kiểm tra khu vực.
NavigationgetRoutes, getDoorToDoorRouteCalculate routes for host-owned summary UI or then render with .route.Tính tuyến cho phần tóm tắt riêng hoặc hiển thị lại bằng .route.
WeathergetWeatherShow weather cards, sheets, or alerts managed by the host app.Hiển thị thẻ thời tiết, sheet hoặc cảnh báo do ứng dụng quản lý.
Road toolssnapToRoads, isochroneProcess tracks, delivery zones, accessibility ranges, or analytics flows.Xử lý vết GPS theo tim đường, vùng giao hàng, vùng đẳng thời (Isochrone) hoặc dữ liệu phân tích.
Static mapgetStaticMap, getStaticMapDataGenerate previews, thumbnails, or share images without showing a live map.Tạo ảnh preview, thumbnail hoặc ảnh chia sẻ mà không cần mở bản đồ live.
GeofencingcheckPointInsidePolygonCheck whether a coordinate belongs to a known polygon.Kiểm tra một tọa độ có nằm trong polygon đã biết hay không.

Examples for every methodVí dụ cho từng hàm

The snippets below use the callback overloads so UIKit host screens can receive results without creating Task blocks. The callback returns the response model plus ResponseMessage.Các ví dụ bên dưới dùng callback để màn UIKit nhận kết quả mà không cần tạo Task. Callback trả model kết quả kèm ResponseMessage.

let center = CLLocationCoordinate2D(latitude: 21.0278, longitude: 105.8342)
let destination = CLLocationCoordinate2D(latitude: 21.0368, longitude: 105.8342)

GtelMapClient.shared.reversePoint(
    pointLat: center.latitude,
    pointLon: center.longitude
) { reverse, reverseMessage in
    guard reverseMessage.onCheckSuccess(), let reverse else { return }
    updateAddress(reverse)
}

GtelMapClient.shared.autocomplete(
    text: "Ho Guom",
    focusLat: center.latitude,
    focusLng: center.longitude,
    size: 10
) { suggestions, autocompleteMessage in
    guard autocompleteMessage.onCheckSuccess() else { return }
    updateSuggestions(suggestions?.features ?? [])
}

GtelMapClient.shared.forwardGeocoding(
    text: "Ho Guom",
    focusLat: center.latitude,
    focusLng: center.longitude,
    size: 10
) { searchResult, searchMessage in
    guard searchMessage.onCheckSuccess() else { return }
    updateSearchResult(searchResult)
}

if let placeId = selectedPlaceId {
    GtelMapClient.shared.getLocationDetail(id: placeId) { detail, detailMessage in
        guard detailMessage.onCheckSuccess(), let detail else { return }
        showPlaceDetail(detail)
    }
}

GtelMapClient.shared.nearbySearch(
    location: center,
    types: "restaurant",
    radius: 1000,
    size: 20
) { nearby, nearbyMessage in
    guard nearbyMessage.onCheckSuccess(), let nearby else { return }
    updateNearbyPlaces(nearby)
}

Callback result styleNhận kết quả bằng callback

For host apps, prefer the callback overloads. They do not require Task at the call site and return both the model and ResponseMessage; the service facade does not throw.Với ứng dụng UIKit, nên dùng dạng callback. Cách này không cần tạo Task tại nơi gọi và trả về cả model lẫn ResponseMessage; service facade không ném lỗi (throw).

GtelMapClient.shared.autocomplete(
    text: "Ha Noi",
    focusLat: 21.0278,
    focusLng: 105.8342,
    size: 10
) { model, message in
    guard message.onCheckSuccess() else {
        showError(message)
        return
    }

    results = model?.features ?? []
}

Fetch first, render laterLấy dữ liệu trước, hiển thị sau

A host screen can calculate data with GtelMapClient, then pass the result into GtelMapView.apply(input:) only when the user opens a map.Một màn hình có thể lấy dữ liệu bằng GtelMapClient trước. Khi người dùng mở bản đồ, truyền kết quả vào GtelMapView.apply(input:).

GtelMapClient.shared.getRoutes(request: request) { route, message in
    guard message.onCheckSuccess(), let route else { return }

    // Later, on the map screen:
    mapView.apply(input: .route(route))
}

GtelPlaceSearchViewControllerGtelPlaceSearchViewController

GtelPlaceSearchViewController is the UIKit v1 search UI. It debounces text input, loads suggestions through GtelMapClient.shared.autocomplete, and reports selection through GtelPlaceSearchDelegate.GtelPlaceSearchViewController là màn hình tìm kiếm UIKit v1. Controller tự chờ người dùng dừng nhập, lấy gợi ý qua GtelMapClient.shared.autocomplete và trả lựa chọn qua GtelPlaceSearchDelegate.

extension MapViewController: GtelPlaceSearchDelegate {
    func showSearch() {
        let searchVC = GtelPlaceSearchViewController()
        searchVC.delegate = self
        searchVC.focusCoordinate = currentMapCenter
        searchVC.searchSize = 10
        present(searchVC, animated: true)
    }

    func placeSearch(_ controller: GtelPlaceSearchViewController, didSelect item: SearchResultItemDataSource) {
        controller.dismiss(animated: true)
        mapView.apply(input: .searchResult(item))
    }

    func placeSearchDidCancel(_ controller: GtelPlaceSearchViewController) {
        controller.dismiss(animated: true)
    }
}

Current limitsGiới hạn hiện tại

Search UI

The first public search UI is UIKit-only. SwiftUI search UI is deferred.Search UI public đầu tiên chỉ hỗ trợ UIKit. Search UI SwiftUI được để sau.

Map styles

Style loading remains a map flow through GtelMapView.apply(input: .mapStyles) and delegate callbacks.Tải style vẫn đi qua GtelMapView.apply(input: .mapStyles) và nhận kết quả bằng delegate callback.

Nearby search

Nearby search remains a map-render flow through .nearbySearch because the SDK converts places into map annotations.Nearby search vẫn đi qua .nearbySearch vì SDK chuyển địa điểm thành marker trên bản đồ.

Rendering

GtelMapClient never renders UI. Any map output still goes through GtelMapView.GtelMapClient không hiển thị UI. Mọi nội dung trên bản đồ vẫn đi qua GtelMapView.

Result, error & lifecycleKết quả, lỗi & vòng đời

Unlike Android which uses Resource<T>, the iOS guide receives map results via GtelMapViewDelegate and direct service results via GtelMapClient.Trên iOS, kết quả từ bản đồ được trả qua GtelMapViewDelegate. Kết quả lấy trực tiếp được trả qua GtelMapClient.

func gtelMapView(_ mapView: GtelMapView, didLoadSearchResults items: [SearchResultItemDataSource]) {
    results = items
}

func gtelMapView(_ mapView: GtelMapView, didFailSearch message: ResponseMessage) {
    showError(message)
}

func gtelMapViewDidFinishLoading(_ mapView: GtelMapView) {
    isMapReady = true
}
UIKit and SwiftUI manage the view lifecycle. With SwiftUI, keep GtelMapView inside UIViewRepresentable and use a coordinator so the delegate is not released prematurely.UIKit và SwiftUI quản lý vòng đời của view. Với SwiftUI, đặt GtelMapView trong UIViewRepresentable và dùng coordinator để delegate không bị giải phóng sớm.

Error callback groupsNhóm callback lỗi

GroupNhómCallbacksCallback
StyledidFailMapStyles, didFailMapStyle, didFailCustomStyleContent(_:message:ResponseMessage), didFailCustomStyleContent(_:error:GtelMapCustomStyleContentError)
SearchdidFailAutocomplete, didFailSearch, didFailNearbySearch, didFailPinPlace, didFailReversePoint
RoutedidFailNavigation, didFailMatrixRoute
OverlaydidFailGeofencing
didFailCustomStyleContent has two overloads. The ResponseMessage version handles network/server errors. The typed GtelMapCustomStyleContentError version handles validation errors (invalid ids, duplicate ids, missing sources, etc.) before any network call is made.didFailCustomStyleContent có hai dạng. Dạng ResponseMessage xử lý lỗi chung. Dạng GtelMapCustomStyleContentError xử lý lỗi dữ liệu như id sai, id trùng hoặc thiếu source.

CheatsheetTra nhanh

The most commonly used inputs, helpers, and callbacks when integrating the host app.Các input, hàm hỗ trợ và callback thường dùng nhất khi tích hợp SDK.

GtelMapViewInput

GroupNhómInput
Search.autocomplete, .forwardGeocoding, .reversePoint, .nearbySearch, .searchResult, .placeDetail, .clearSearch
Map.mapStyles, .mapStyle, .mapStyleSource
Annotation.marker, .annotations, .pinnedPlace, .clearRouteAndMarker
Route.navigationAvailableModes, .navigationRoute, .route, .multiStopRoute, .matrixRoute, .matrixCandidateRoutes, .clearRoute
Overlay.polygon, .clearPolygon, .geofencingPolygon, .isochrone, .clearIsochrone, .snapToRoads, .snapToRoadsPlayback, .clearSnapToRoads
Custom style.customStyleImage, .removeCustomStyleImage, .customStyleContent, .updateCustomStyleSource, .updateCustomStyleFeature, .removeCustomStyleFeature, .removeCustomStyleContentById, .removeCustomStyleContent, .clearCustomStyleContent, .setCustomStyleLayerVisibility, .setCustomStyleLayerFilter, .clearCustomStyleLayerFilter

GtelMapView helpers

HelperHelperPurposeMục đích
setCameraZoomToAtFocus on a coordinate.Đưa camera tới một tọa độ.
setCameraToUserLocationFocus on user location.Đưa camera tới vị trí người dùng.
setCameraBoundsInVietNamDefault Vietnam viewport.Vùng bản đồ mặc định Việt Nam.
setCameraDefaultMap(sw:ne:edgePadding:)Fit to custom bounds.Đưa camera vừa với vùng tùy chỉnh.
visiableBoundsCurrent visible bounds (read-only).Vùng bản đồ đang hiển thị.
onSetVisiableBounds(annotations:) / onSetVisiableBounds(points:)Fit camera to show all annotations or coordinates.Đưa camera vừa đủ để thấy tất cả marker hoặc tọa độ.
removeAllAnnotations · deselectAllCalloutClear markers or callout.Xóa marker hoặc callout.
isValidCoordinateValidate before camera or marker calls.Kiểm tra tọa độ trước khi gọi camera hoặc marker.
getRoutes · getDoorToDoorRouteFetch route data without rendering.Lấy dữ liệu tuyến đường mà chưa hiển thị lên bản đồ.
getWeather · snapToRoads · isochrone · getStaticMapDirect service helpers with callback.Các hàm lấy dữ liệu trực tiếp và trả kết quả qua callback.
reversePoint(pointLat:pointLon:callback:)Direct reverse geocoding without delegate.Lấy địa chỉ từ tọa độ mà không đi qua delegate.
handlePOICalloutTap · handlePOICalloutDirectionRespond to POI callout button taps.Xử lý nút trong callout của POI.
calloutAnchorPoint(for:)Anchor point for custom overlays aligned to callout.Lấy vị trí để căn overlay theo callout.
scheduleOverlayPositionUpdateTrigger overlay position recalculation.Yêu cầu tính lại vị trí overlay.
showUserCurrentLocationShow the user location dot on the map.Hiển thị chấm vị trí người dùng trên bản đồ.

GtelMapViewDelegateGtelMapViewDelegate

GroupNhómCallbacksCallback
Lifecycle & stylegtelMapViewDidFinishLoading, gtelMapViewDidFinishLoadingStyle, gtelMapViewRegionIsChanging, didChangeRegion, regionWillChangeWith, regionDidChangeWith
InteractiondidTapCoordinate, didPinCoordinate, didTouchAnnotation, gtelMapViewDidBeginGesturePan, gtelMapViewDidEndGesturePan
CalloutcanShowCalloutFor, annotationViewFor, markerImageFor, leftCalloutAccessoryViewFor, rightCalloutAccessoryViewFor, didShowCallout, didUpdateCalloutSubtitle, didUpdateCalloutCategory, gtelMapViewDidRemoveCallout, didRequestCalloutPositionUpdate
POIdidRequestPlaceDetail, didLoadPOIDetail, didTapCustomFeature
SearchdidLoadMapStyles, didLoadSearchResults, didLoadAutocompleteResults, didLoadNearbySearch, didLoadPlaceDetail, didLoadReversePoint, didLoadPinPlace
RoutingdidLoadNavigationModes, didLoadNavigationRoute, didSelectNavigationRoute, didSelectMainTrip, didRequestDirection, didLoadMatrixRoute
GeofencingdidLoadGeofencingResult, didFailGeofencing

TroubleshootingXử lý sự cố

Quick checklist when integrating the SDK into the host app.Danh sách kiểm tra nhanh khi tích hợp SDK.

SymptomHiện tượngCheckKiểm tra
Map blank or style not loadingBản đồ trắng hoặc style không tảiVerify the SDK is configured before the map is created, GTELMapAccessToken is set in Info.plist, and the device has network. Call GtelMapConfig.hasAPIKey to verify.Kiểm tra SDK đã được cấu hình trước khi tạo bản đồ, GTELMapAccessToken đã có trong Info.plist và thiết bị có mạng. Có thể gọi GtelMapConfig.hasAPIKey để kiểm tra.
Delegate callbacks not receivedKhông nhận callback từ delegateEnsure gtelMapDelegate is alive and set before sending any input.Đảm bảo gtelMapDelegate còn tồn tại và đã được gắn trước khi gửi input.
Search not updating UITìm kiếm không cập nhật giao diệnImplement the correct success/fail callbacks, debounce input text, and clear search when the query is empty.Cài đặt đúng callback thành công/lỗi, chờ người dùng dừng nhập rồi mới tìm kiếm, và gọi .clearSearch khi ô tìm kiếm rỗng.
Marker or callout not visibleMarker hoặc callout không hiển thịCheck the AnnotationModel, the custom icon returned from the delegate, and the callout deselect state.Kiểm tra AnnotationModel, icon tùy chỉnh trả về từ delegate và trạng thái chọn callout.
Route / navigation failsTuyến đường hoặc dẫn đường bị lỗiVerify the location list has enough valid waypoints, a travel mode is selected, and check the didFailNavigation callback.Kiểm tra danh sách có đủ điểm hợp lệ, đã chọn phương tiện di chuyển và xem callback didFailNavigation.
Location not workingVị trí không hoạt độngCheck the Info.plist usage description, device permission, and the coordinate value before calling the camera.Kiểm tra mô tả quyền trong Info.plist, quyền trên thiết bị và tọa độ trước khi gọi camera.
Custom style content fails with rendererNotReadyCustom style content báo lỗi rendererNotReadyWait for gtelMapViewDidFinishLoading before sending .customStyleContent. For style switches, use gtelMapViewDidFinishLoadingStyle.Chờ gtelMapViewDidFinishLoading rồi mới gửi .customStyleContent. Khi đổi style, dùng gtelMapViewDidFinishLoadingStyle.
Custom content id / layer id validation errorCustom content id hoặc layer id không hợp lệAll host app ids and image names must start with host_. See GtelMapCustomStyleContentError for the specific error type.Tất cả id và tên hình do ứng dụng đặt phải bắt đầu bằng host_. Xem GtelMapCustomStyleContentError để biết lỗi cụ thể.
POI tap does not trigger detailChạm POI nhưng không có chi tiếtVerify the didLoadPOIDetail callback is implemented on the delegate. POI detail requires network and a valid API key.Kiểm tra delegate đã cài đặt didLoadPOIDetail. Chi tiết POI cần mạng và API key hợp lệ.
GtelRouteNavigationViewController does not load routeGtelRouteNavigationViewController không tải tuyến đườngEnsure at least 2 valid coordinates are passed in stops. Check the API key and network.Đảm bảo truyền ít nhất 2 tọa độ hợp lệ vào stops. Kiểm tra API key và mạng.

Your first mapHiển thị bản đồ đầu tiên

Minimal example: configure the SDK, create GtelMapView, assign the delegate, and move the camera to the default viewport.Ví dụ tối thiểu: cấu hình SDK, tạo GtelMapView, gắn delegate và đưa camera về vùng mặc định.

API GtelMapConfig · GtelMapView UI UIKit Time ~5 min

Integration stepsCác bước tích hợp

  1. Configure the SDK once during app launch.Cấu hình SDK một lần khi app khởi động.
  2. Create GtelMapView in the screen.Tạo GtelMapView trong màn hình.
  3. Assign gtelMapDelegate before sending any input.Gắn gtelMapDelegate trước khi gửi input.
  4. Wait for map loading callback before moving to the default viewport.Chờ callback báo bản đồ đã tải xong rồi mới đưa camera về vùng mặc định.
final class FirstMapViewController: UIViewController, GtelMapViewDelegate {
    private let mapView = GtelMapView()

    override func viewDidLoad() {
        super.viewDidLoad()
        mapView.gtelMapDelegate = self
        view.addSubview(mapView)
        mapView.frame = view.bounds
        mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    }

    func gtelMapViewDidFinishLoading(_ mapView: GtelMapView) {
        mapView.setCameraBoundsInVietNam()
    }
}

Next stepsBước tiếp theo

Switch style at runtimeĐổi style

Load the style catalog once, show a picker in the host UI, then apply the selected style.Tải danh sách style một lần, hiển thị bộ chọn trong giao diện ứng dụng, rồi áp dụng style được chọn.

Input .mapStyles Input .mapStyle Callback didLoadMapStyles
func prepareStylePicker() {
    mapView.apply(input: .mapStyles)
}

func gtelMapView(_ mapView: GtelMapView, didLoadMapStyles items: [GtelMapStyleModel]) {
    styleItems = items
}

func userDidSelectStyle(_ style: GtelMapStyleModel) {
    mapView.apply(input: .mapStyle(style))
}
After a style reload, re-apply any host-owned custom style content that should remain visible.Sau khi style tải lại, gửi lại custom style content nếu các lớp đó vẫn cần hiển thị.

Custom style (dynamic)Custom style

Add a custom content block, then update individual features without re-adding the entire block. Handle taps on custom features via the delegate.Thêm một custom content block, sau đó cập nhật từng feature khi dữ liệu thay đổi. Khi người dùng chạm feature, xử lý qua delegate.

Input .customStyleContent Input .updateCustomStyleFeature Callback didTapCustomFeature
// 1. Register icon and add content block once
func setupVehicleLayer(vehicles: [Vehicle]) {
    mapView.apply(input: .customStyleImage(name: "host_ic_vehicle", image: UIImage(named: "ic_vehicle")!))

    let features = vehicles.map { v in
        GtelMapCustomFeature(
            id: v.id,
            geometry: .point(v.coordinate),
            title: v.name,
            properties: ["status": v.status]
        )
    }
    let source = GtelMapCustomSource(id: "host_vehicles_source", features: features)
    let layer = GtelMapCustomLayer(
        id: "host_vehicles_layer",
        sourceId: "host_vehicles_source",
        kind: .symbol,
        style: GtelMapCustomLayerStyle(iconScale: 1.2, showsTitle: true)
    )
    let content = GtelMapCustomStyleContent(
        id: "host_vehicles",
        sources: [source],
        layers: [layer]
    )
    mapView.apply(input: .customStyleContent(content: content))
}

// 2. Update a single vehicle position without re-adding everything
func updateVehicle(_ vehicle: Vehicle) {
    let updated = GtelMapCustomFeature(
        id: vehicle.id,
        geometry: .point(vehicle.coordinate),
        title: vehicle.name,
        properties: ["status": vehicle.status]
    )
    mapView.apply(input: .updateCustomStyleFeature(
        contentId: "host_vehicles",
        sourceId: "host_vehicles_source",
        feature: updated
    ))
}

// 3. Handle taps
func gtelMapView(_ mapView: GtelMapView, didTapCustomFeature feature: GtelMapCustomFeature, layerId: String?) {
    guard let vehicleId = feature.id else { return }
    showVehicleDetail(id: vehicleId)
}

// 4. Clean up when leaving the screen
func cleanup() {
    mapView.apply(input: .removeCustomStyleContentById(contentId: "host_vehicles"))
}

Markers + callout from a listMarker + callout từ danh sách

Render a list of places as annotations and adapt the host app UI based on marker/callout callbacks.Hiển thị danh sách địa điểm thành marker. Cập nhật giao diện theo callback của marker hoặc callout.

Input .annotations Helper onSetVisiableBounds Callback didShowCallout
func renderPlaces(_ places: [AnnotationModel]) {
    mapView.apply(input: .annotations(places, layerId: "nearby_places", visibleLayerIds: ["nearby_places"], iconScale: 1.0))
    mapView.onSetVisiableBounds(annotations: places)
}

func gtelMapView(_ mapView: GtelMapView, didShowCallout annotation: AnnotationModel, isLoadingSubtitle: Bool) {
    showPlacePreview(annotation)
}

Autocomplete + debounceGợi ý tìm kiếm tự động (Debounce Autocomplete)

The host app debounces text by about 250 ms, uses the current center as the focus, then renders the suggestion list from the delegate.Ứng dụng nên chờ khoảng 250 ms sau khi người dùng dừng nhập. Sau đó dùng tâm bản đồ hiện tại để lấy gợi ý và hiển thị danh sách nhận từ delegate.

Debounce ~250 ms Input .autocomplete Callback didLoadAutocompleteResults
func searchTextDidChange(_ text: String, focus: CLLocationCoordinate2D) {
    searchDebouncer.run { [weak self] in
        guard !text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else {
            self?.mapView.apply(input: .clearSearch)
            return
        }
        self?.mapView.apply(input: .autocomplete(text: text, focusLat: focus.latitude, focusLng: focus.longitude, size: 8))
    }
}

func gtelMapView(_ mapView: GtelMapView, didLoadAutocompleteResults items: [SearchResultItemDataSource]) {
    suggestions = items
}

Selecting a suggestionChọn một gợi ý

func userDidSelectSuggestion(_ item: SearchResultItemDataSource) {
    mapView.apply(input: .searchResult(item))
    if !item.placeId.isEmpty {
        mapView.apply(input: .placeDetail(item.placeId))
    }
}

Tap / long-press → reverse geocodeChạm / nhấn giữ → Địa mã hóa nghịch (Reverse Geocoding)

When the user taps or pins a coordinate, send the reverse point input so the SDK resolves the place and renders a marker if needed.Khi người dùng chạm hoặc nhấn giữ một tọa độ, gửi input reverse point để SDK tìm địa điểm và hiển thị marker nếu cần.

func gtelMapView(_ mapView: GtelMapView, didPinCoordinate coordinate: CLLocationCoordinate2D) {
    mapView.apply(input: .reversePoint(coordinate: coordinate, showMarker: true, zoom: 18, size: 1))
}

func gtelMapView(_ mapView: GtelMapView, didLoadReversePoint place: GeocodingResponseModel?, coordinate: CLLocationCoordinate2D) {
    pinnedPlace = place
}

POI tap flowLuồng chạm POI trên bản đồ

Handle the full lifecycle of a map POI tap: callout → loading → detail → action buttons.Khi người dùng chạm POI, SDK hiển thị callout, tải dữ liệu, trả chi tiết và cho phép xử lý các nút thao tác.

Auto SDK-triggered on map tap Callback didShowCallout · didLoadPOIDetail Helper handlePOICalloutTap
// No input needed — SDK handles POI tap automatically.
// The host app just implements delegate callbacks.

extension MapViewController: GtelMapViewDelegate {
    // Step 1: callout appears with title from map data
    func gtelMapView(_ mapView: GtelMapView, didShowCallout annotation: AnnotationModel, isLoadingSubtitle: Bool) {
        showCalloutView(title: annotation.title ?? "", isLoading: isLoadingSubtitle)
    }

    // Step 2: subtitle (address) resolves asynchronously
    func gtelMapView(_ mapView: GtelMapView, didUpdateCalloutSubtitle subtitle: String) {
        calloutView.subtitleLabel.text = subtitle
    }

    // Step 3: category resolves (update icon in callout)
    func gtelMapView(_ mapView: GtelMapView, didUpdateCalloutCategory type: String) {
        calloutView.categoryIcon.image = categoryIcon(for: type)
    }

    // Step 4: full detail available — populate bottom sheet
    func gtelMapView(_ mapView: GtelMapView, didLoadPOIDetail detail: PlaceDetailModel) {
        bottomSheet.populate(
            name: detail.name,
            address: detail.adrFormatAddress ?? detail.formattedAddress,
            phone: detail.internationalPhoneNumber,
            types: detail.types
        )
        bottomSheet.show()
    }

    // Step 5: user taps "Navigate" button in host UI
    @IBAction func navigateButtonTapped() {
        mapView.handlePOICalloutDirection()
    }

    // Step 6: callout dismissed
    func gtelMapViewDidRemoveCallout(_ mapView: GtelMapView) {
        bottomSheet.hide()
    }
}

Route A → BTuyến đường A → B

Request a route from two valid points, auto-render the route, and clear it when leaving the flow.Gửi hai điểm hợp lệ để SDK tìm tuyến đường. SDK sẽ hiển thị tuyến tự động; khi rời màn hình, gọi lệnh xóa tuyến.

Input .navigationRoute Mode TransportType Callback didLoadNavigationRoute
func route(from origin: LocationDataRequest, to destination: LocationDataRequest) {
    mapView.apply(input: .navigationRoute(locations: [origin, destination], costing: .auto))
}

func gtelMapView(_ mapView: GtelMapView, didLoadNavigationRoute route: RouteResponseModel, selectedTrip: TripModel?) {
    routeInfo = selectedTrip
}

func clearRouteFlow() {
    mapView.apply(input: .clearRoute)
}

Common variantsBiến thể thường dùng

GoalMục tiêuUseCách dùng
Render only, no network requestChỉ hiển thị, không gọi mạng.route(response)
Clear route when closing screenXóa route khi đóng màn hình.clearRoute or .clearRouteAndMarker
Show a multi-stop routeHiển thị tuyến đường nhiều điểm trung chuyển (Multi-stop Route).multiStopRoute(response:stops:)

Navigation modes & routeChế độ dẫn đường & tuyến đường

Retrieve available modes first, let the user choose, then request a navigation route with the selected mode.Lấy danh sách phương tiện trước, để người dùng chọn, rồi yêu cầu tuyến đường bằng phương tiện đã chọn.

func prepareNavigation(_ locations: [LocationDataRequest]) {
    mapView.apply(input: .navigationAvailableModes(locations))
}

func gtelMapView(_ mapView: GtelMapView, didLoadNavigationModes items: [TransportItemModel], selected: TransportType?, locations: [LocationDataRequest]) {
    let costing = selected ?? .auto
    mapView.apply(input: .navigationRoute(locations: locations, costing: costing))
}

Turn-by-turn navigationDẫn đường từng ngã rẽ (Turn-by-turn)

Present GtelRouteNavigationViewController to launch the full navigation UI. The SDK handles map tracking, voice instructions, and the summary panel. Use .demo mode during development to simulate movement without a physical drive.Present GtelRouteNavigationViewController để mở giao diện dẫn đường đầy đủ. SDK tự theo dõi bản đồ, đọc hướng dẫn và hiển thị tóm tắt. Dùng .demo khi phát triển để giả lập di chuyển.

Class GtelRouteNavigationViewController Mode .live · .demo Time ~3 min
func startNavigation(from origin: CLLocationCoordinate2D, to destination: CLLocationCoordinate2D) {
    let navVC = GtelRouteNavigationViewController(
        stops: [origin, destination],
        profile: .car,
        language: "vi",
        mode: .live
    )
    navVC.modalPresentationStyle = .fullScreen
    present(navVC, animated: true)
}

// Demo mode — useful for testing in Simulator
func startDemoNavigation(from origin: CLLocationCoordinate2D, to destination: CLLocationCoordinate2D) {
    let navVC = GtelRouteNavigationViewController(
        stops: [origin, destination],
        profile: .car,
        language: "vi",
        mode: .demo
    )
    navVC.modalPresentationStyle = .fullScreen
    present(navVC, animated: true)
}

// Multi-stop
func startMultiStopNavigation(stops: [CLLocationCoordinate2D]) {
    let navVC = GtelRouteNavigationViewController(
        stops: stops,
        profile: .car,
        language: "vi",
        mode: .live
    )
    present(navVC, animated: true)
}

Door-to-door routeĐịnh tuyến điểm đầu - điểm cuối toàn diện (Door-to-Door Routing)

Fetch a door-to-door route (includes last-mile walking legs) and show the summary before the user starts navigation.Định tuyến điểm đầu - điểm cuối toàn diện (Door-to-Door Routing), tự động bổ sung các đoạn đi bộ kết nối và hiển thị tóm tắt trước khi bắt đầu dẫn đường.

Helper GtelMapClient.shared.getDoorToDoorRoute Returns RouteResponseModel
func loadDoorToDoorPreview(origin: LocationDataRequest, destination: LocationDataRequest) {
    let request = EstimateTimeDataRequest(
        origin: origin,
        destination: destination,
        costing: .auto
    )
    GtelMapClient.shared.getDoorToDoorRoute(request: request) { [weak self] response, message in
        guard let self, message.onCheckSuccess(), let trip = response?.trip else {
            self?.showError(message.getDes())
            return
        }
        self.showDoorToDoorSummary(
            totalDistance: trip.summary?.length,
            totalTime: trip.summary?.time,
            legs: trip.legs
        )
        if let response { self.mapView.apply(input: .route(response)) }
    }
}

User Location + focus cameraVị trí người dùng + camera

After the host app requests location permission and receives a coordinate, validate it and focus the camera.Sau khi ứng dụng xin quyền vị trí và nhận tọa độ, kiểm tra tọa độ rồi đưa camera tới vị trí đó.

Host CLLocationManager Helper isValidCoordinate Helper setCameraToUserLocation
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    guard let coordinate = locations.last?.coordinate, mapView.isValidCoordinate(coordinate) else {
        mapView.setCameraBoundsInVietNam()
        return
    }
    mapView.setCameraToUserLocation(coordinate: coordinate, zoomLevel: 16)
}

Geofencing checkKiểm tra hàng rào địa lý ảo (Geofencing)

Check whether a point is inside a polygon boundary and render the fence on the map. The SDK fires didLoadGeofencingResult with an isInside flag.Kiểm tra một điểm có nằm trong polygon hay không và hiển thị vùng đó trên bản đồ. SDK trả kết quả qua didLoadGeofencingResult với cờ isInside.

Input .geofencingPolygon Callback didLoadGeofencingResult
func checkGeofence(vehicleId: String, vehicleCoordinate: CLLocationCoordinate2D, zone: PolygonGeometryModel) {
    mapView.apply(input: .geofencingPolygon(
        pointId: vehicleId,
        coordinate: vehicleCoordinate,
        geometry: zone
    ))
}

func gtelMapView(_ mapView: GtelMapView, didLoadGeofencingResult pointId: String, isInside: Bool) {
    if isInside {
        showAlert("\(pointId) is inside the zone")
    } else {
        showAlert("\(pointId) has left the zone")
    }
}

func gtelMapView(_ mapView: GtelMapView, didFailGeofencing message: ResponseMessage) {
    showError(message.getDes())
}

Isochrone zonesVùng đẳng thời (Isochrone)

Fetch reachability polygons for a given origin and travel times, then render them as overlays on the map.Lấy các vùng có thể tiếp cận từ một điểm xuất phát theo thời gian di chuyển, rồi hiển thị chúng thành lớp phủ trên bản đồ.

Helper GtelMapClient.shared.isochrone Input .isochrone Input .clearIsochrone
func showIsochroneZones(from coordinate: CLLocationCoordinate2D) {
    let request = IsochroneRequest(
        lat: coordinate.latitude,
        lng: coordinate.longitude,
        contours: [5, 10, 15],      // minutes
        costing: .auto
    )
    GtelMapClient.shared.isochrone(request: request) { [weak self] response, message in
        guard let self, message.onCheckSuccess(), let response else { return }
        self.mapView.apply(input: .isochrone(
            response: response,
            originCoordinate: coordinate,
            callouts: nil
        ))
    }
}

func clearZones() {
    mapView.apply(input: .clearIsochrone)
}