Take a map offline using a preplanned map area.
Use case
Generating offline maps on demand for a specific area can be time consuming for users and a processing load on the server. If areas of interest are known ahead of time, a web map author can pre-create packages for these areas. This way, the generation only needs to happen once, making the workflow more efficient for users and servers.
An archeology team could define preplanned map areas for dig sites which can be taken offline for field use. To see the difference, compare this sample to the "Generate offline map" sample.
How to use the sample
Select a preplanned map area by tapping the "Select Map" button and selecting one of the showing available areas. Tapping a cell initiates a download, and shows download progress in the interim. Once downloaded, the preplanned map is displayed in the map view. If a preplanned map is reselected later, the locally cached data is loaded immediately.
How it works
- Create a
Map
instance from aPortalItem
. - Create an
OfflineMapTask
instance from the portal item. - Load the offline map task's
PreplannedMapArea
s. - To download a selected map area, create the default parameters with the offline map task's
makeDefaultDownloadPreplannedOfflineMapParameters(preplannedMapArea:)
method, specifying the selected map area. - Set the parameter's update mode.
- Create a
DownloadPreplannedOfflineMapJob
instance with the offline map task'smakeDownloadPreplannedOfflineMapJob(parameters:downloadDirectory:)
method, passing in the parameters and a download directory as arguments. - Start the job and await its output.
- Get the offline
Map
from the output when the job successfully finishes. - Update the map with the offline map.
Relevant API
- DownloadPreplannedOfflineMapResult
- OfflineMapTask
- OfflineMapTask.makeDefaultDownloadPreplannedOfflineMapParameters(preplannedMapArea:)
- OfflineMapTask.makeDownloadPreplannedOfflineMapJob(parameters:downloadDirectory:)
- PreplannedMapArea
About the data
The Naperville water network map is based on ArcGIS Solutions for Stormwater and provides a realistic depiction of a theoretical stormwater network.
Additional information
DownloadPreplannedOfflineMapParameters.updateMode
can be used to set the way the preplanned map area receives updates in several ways:
noUpdates
: No updates will be performed. This mode is intended for when a static snapshot of the data is required, and it does not create a replica. This is the mode used for this sample.syncWithFeatureServices
: Changes, including local edits, will be synced directly with the underlying feature services. This is the default update mode.downloadScheduledUpdates
: Scheduled, read-only updates will be downloaded from the online map area and applied to the local mobile geodatabases.downloadScheduledUpdatesAndUploadNewFeatures
: An advanced workflow where scheduled, read-only updates will be downloaded from the online map area and applied to the local mobile geodatabases, and new features added on the client side can also be synchronized with the server.
For more information about offline workflows, see Offline maps, scenes, and data on the Esri Developer website.
Tags
map area, offline, pre-planned, preplanned
Sample Code
// Copyright 2022 Esri
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import ArcGIS
import SwiftUI
struct DownloadPreplannedMapAreaView: View {
/// A Boolean value indicating whether to select a map.
@State private var isShowingSelectMapView = false
/// A Boolean value indicating whether to show delete alert.
@State private var isShowingDeleteAlert = false
/// The view model for this sample.
@StateObject private var model = Model()
var body: some View {
MapView(map: model.currentMap, viewpoint: model.currentMap.initialViewpoint?.expanded())
.overlay(alignment: .top) {
mapNameOverlay
}
.toolbar {
ToolbarItemGroup(placement: .bottomBar) {
Spacer()
Button("Select Map") {
isShowingSelectMapView.toggle()
}
.popover(isPresented: $isShowingSelectMapView) {
MapPicker(model: model)
.presentationDetents([.fraction(0.5)])
.frame(idealWidth: 320, idealHeight: 380)
}
Spacer()
Button {
isShowingDeleteAlert = true
} label: {
Image(systemName: "trash")
}
.disabled(!model.canRemoveDownloadedMaps)
.alert("Delete All Offline Areas", isPresented: $isShowingDeleteAlert) {
Button("Delete", role: .destructive) {
model.removeDownloadedMaps()
}
} message: {
Text("Are you sure you want to delete all downloaded preplanned map areas?")
}
}
}
.task {
// Makes the offline map models when the view is first shown.
await model.makeOfflineMapModels()
}
}
private var mapNameOverlay: some View {
Text(model.currentMap.item?.title ?? "Unknown Map")
.font(.footnote)
.frame(maxWidth: .infinity)
.padding(8)
.background(.thinMaterial, ignoresSafeAreaEdges: .horizontal)
}
}
private extension Viewpoint {
/// Expands the viewpoint's geometry.
/// - Returns: A viewpoint with it's geometry expanded by 50%.
func expanded() -> Viewpoint {
let builder = EnvelopeBuilder(envelope: self.targetGeometry.extent)
builder.expand(by: 0.5)
let zoomEnvelope = builder.toGeometry()
return Viewpoint(boundingGeometry: zoomEnvelope)
}
}
#Preview {
NavigationStack {
DownloadPreplannedMapAreaView()
}
}