Loading the Region Catalog

After initialization, synchronize the routing catalog and read the combined region list. The combined list contains routing catalog entries, map catalog entries, and installed map packages by regionId.

Sync and read the region list

1
@MainActor
2
func reloadRegions() async throws {
3
_ = try await NBNavigation.syncOfflineRegionList(syncMode: .auto)
4
5
// nil or an empty array returns every country.
6
let result = await NBNavigation.fetchRegionLists()
7
rows = result.regionRows
8
9
if let routeError = result.routeError {
10
showComponentWarning("Routing catalog: \(routeError)")
11
}
12
if let mapError = result.mapError {
13
showComponentWarning("Map catalog: \(mapError)")
14
}
15
if let installedError = result.mapInstalledError {
16
showComponentWarning("Installed maps: \(installedError)")
17
}
18
}

Note that syncOfflineRegionList(syncMode: .auto) uses the cache freshness policy. For an explicit user refresh use .force. Also, fetchRegionLists does not synchronize catalogs and it does not fail the entire request when one component fails. Instead, it reports component errors through routeError, mapError, and mapInstalledError, so the screen can display content that loaded successfully.

Catalog API comparison

MethodNetwork accessResultRecommended use
syncOfflineRegionListMay access the networkSynchronizes the routing catalog according to the selected sync mode, then returns the locally cached catalog filtered by countries.Initial load or refresh
listOfflineRegionsDoes not synchronize automaticallyReads the locally cached routing catalog without synchronizing it.Offline access and local state
fetchRegionListsReads the current component catalogsCombines routing data, maps, and installed packages while preserving component-level errorsUnified management screen

Region List Item Fields

FieldMeaningRecommended use
regionIdRegion identifier used by the current routing and map catalogs and as the join key for region-management APIs.Use it for list diffing, caching, and every download, pause, resume, cancel, delete, and progress API. Do not use displayName as a key.
displayNameMerged display name. The SDK prefers the routing name, then the map-catalog name, the installed-map name, and finally regionId.Use for display only. The name may change with catalog content or localization.
country / adminL1 / adminL2 / adminL3Merged administrative hierarchy. Values are optional, and the map catalog does not provide adminL2.Use for grouping, filtering, and breadcrumbs. Handle nil and do not assume that every level exists.
routeRegionOfflineRegionLeaf from the current routing catalog.Read routing version, estimated size, download state, update state, and bounds. nil means that this merged result has no available routing-catalog entry.
mapRegionOfflineMapCatalogEntry from the current map catalog.Read map version, estimated size, tile count, and map update state. nil means that this merged result has no available map-catalog entry.
mapInstalledRegionOfflineMapInstalledRegionEntry for map packages installed on the device.Determine whether a map is installed and whether all packages are valid. nil usually means that no local map package exists for the region.
routeSizeBytesEstimated total size declared by the routing catalog, in bytes. Present only when routeRegion exists.Use for pre-download display or capacity estimates. It is not the live downloaded or remaining byte count.
mapSizeBytesThe map-catalog estimated size, or the installed map-package total when no map-catalog entry is available, in bytes.Use for size display. Because the source may be a catalog estimate or local package total, do not treat it as remaining download bytes.

fetchRegionLists returns regionRows merged by regionId from the routing catalog, the map catalog, and locally installed map packages. Optional values in a row may be “nil”, so evaluate each dataset independently. A missing component object does not by itself mean that downloaded data was lost.

Useful Nested Fields

The following fields cover the common status, version, and diagnostic needs of an offline-region management screen.

FieldMeaningGuidance
routeRegion.downloadStatusRouting download state: idle, downloading, complete, partial, failed, paused, or unknown.Use for routing-specific status text. For combined controls, prefer overallState from observeOfflineRegionProgress.
routeRegion.tilesDone / tilesTotalNumber of routing tiles written and total routing tiles.Use for local-state diagnostics. Use the progress observation APIs for live download progress.
routeRegion.isDownloaded / isPartialCompletion and partial-download flags calculated by the SDK from the status and tile counts.Prefer these properties instead of duplicating completion rules in the application.
routeRegion.versionRouting-data version in the current catalog.Use for diagnostics or display. Use updateAvailable for the update decision instead of comparing strings alone.
routeRegion.timestampSec / dataVersionLabelCatalog version timestamp and the SDK-formatted yyyy-MM-dd value.Use timestampSec for custom formatting and dataVersionLabel for a simple display value.
routeRegion.totalSizeBytes / sizeWithUnitEstimated routing size in bytes and the SDK-formatted size string.Use totalSizeBytes for consistent app-wide formatting or sizeWithUnit for quick display.
routeRegion.detailSyncStatusRouting-detail synchronization status. Current common values are ok, missing, and stale.Use for detailed diagnostics. Do not treat it as a download state.
routeRegion.updateAvailable“true” when downloaded routing data has a newer catalog version. The SDK compares the current catalog with the stored detail version and timestamp.Show an update action after catalog refresh. Uninstalled, incomplete, or catalog-removed regions are not marked as updates solely for those conditions.
routeRegion.catalogRemovedA local record or data exists, but the region is no longer present in the current routing catalog.Do not offer a new download. You may let the user keep or delete the local data.
routeRegion.boundaryBboxOptional minimum longitude and latitude bounding box for the region.Use for viewport intersection or coarse preview positioning. It is not the precise administrative polygon.
mapRegion.versionOptional version in the current map catalog.Use for diagnostics or display. Use mapRegion.updateAvailable for the update decision.
mapRegion.totalSizeBytes / tileCountEstimated total map size in bytes and number of map tiles in the catalog.Use for pre-download capacity information and catalog diagnostics.
mapRegion.updateAvailable“true” when a map is already installed and either the catalog version differs or the local packages are incomplete.Show an update or repair action after refresh. This is false for an uninstalled map; use mapInstalledRegion == nil to detect that case.
mapInstalledRegion.regionVersionOptional version of the locally installed map packages.Compare with mapRegion.version for diagnostics; keep business update state based on mapRegion.updateAvailable.
mapInstalledRegion.packageCount / totalBytesNumber of local map packages and their total byte count.Use for the installed-content summary and local storage display.
mapInstalledRegion.allPackagesOktrue when every map package for the region passes the integrity check.Treat this as a key map-readiness condition. When false, offer retry or update.
mapInstalledRegion.dataSourceId / dataSourceLabelIdentifier and readable label for the installed map data source.Use for diagnostics or an advanced information screen. Do not use it in place of regionId.

Checking Size Download State and Updates

Refresh the catalogs through the normal screen flow before reading regionRows. The following example evaluates installed and update states separately and shows a combined size only when at least one size is known:

1
import Foundation
2
3
_ = try await NBNavigation.syncOfflineRegionList(syncMode: .auto)
4
let result = await NBNavigation.fetchRegionLists()
5
6
let formatter = ByteCountFormatter()
7
formatter.countStyle = .file
8
9
for row in result.regionRows {
10
let knownBytes = [row.routeSizeBytes, row.mapSizeBytes]
11
.compactMap { $0 }
12
.reduce(0, +)
13
let hasKnownSize = row.routeSizeBytes != nil || row.mapSizeBytes != nil
14
let packageSizeText = hasKnownSize
15
? formatter.string(fromByteCount: knownBytes)
16
: "--"
17
18
let routingDownloaded = row.routeRegion?.isDownloaded == true
19
let mapInstalled = row.mapInstalledRegion != nil
20
let mapPackagesReady = row.mapInstalledRegion?.allPackagesOk == true
21
22
let routingUpdateAvailable = row.routeRegion?.updateAvailable == true
23
let mapUpdateAvailable = row.mapRegion?.updateAvailable == true
24
let anyUpdateAvailable = routingUpdateAvailable || mapUpdateAvailable
25
26
// Render row.displayName, packageSizeText, installed state,
27
// and anyUpdateAvailable in the region list UI.
28
}
  • Size fields: routeSizeBytes and mapSizeBytes are suitable for pre-download estimates. During a download, read downloaded, total, and percent from observeOfflineRegionProgress or observeUnifiedOfflineProgress.
  • Update fields: fetchRegionLists reads the current catalog snapshot and does not synchronize it. To check for the latest update, refresh the catalogs first, then read routeRegion.updateAvailable and mapRegion.updateAvailable.
  • Partial failure: regionRows may still contain data from another component when routeError, mapError, or mapInstalledError is set. Display the available content and offer retry for the failed component.

Result Level Fields

FieldMeaning
routeRegionListRaw routing catalog for screens that need routing sections or leaves.
mapRegionListRaw map catalog and total count for map-catalog diagnostics or a map-only list.
mapInstalledRegionListRaw list of map regions installed on the device.
routeError / mapError / mapInstalledErrorPer-component errors. A value in one field does not make all regionRows unusable.
updatedAtTime when the SDK created this merged result, not the catalog version time or data publication time.

Offline Download Screen Lifecycle

Pair the screen ownership calls:

1
override func viewWillAppear(_ animated: Bool) {
2
super.viewWillAppear(animated)
3
NBNavigation.beginDownloadPageWithOwner(self)
4
NBNavigation.onOfflineMapViewWillAppear()
5
NBNavigation.registerOfflineMapStyle(
6
mapView: previewMapView,
7
styleURL: previewMapView.styleURL
8
)
9
}
10
11
override func viewDidDisappear(_ animated: Bool) {
12
super.viewDidDisappear(animated)
13
NBNavigation.endDownloadPage()
14
}

endDownloadPage releases screen ownership but does not cancel region downloads that have already started.