Add KML layer

View on GitHub

Display KML from a URL, portal item, or local KML file.

Screenshot of Add KML layer sample

Use case

Keyhole Markup Language (KML) is a data format used by Google Earth. KML is popular as a transmission format for consumer use and for sharing geographic data between apps. You can use the Maps SDKs to display KML files, with full support for a variety of features, including network links, 3D models, screen overlays, and tours.

How to use the sample

Use the picker to select a source. A KML layer created from that source will then be displayed in the map.

How it works

  1. To create a KML layer from a URL, create a KMLDataset with the URL to the KML file. Then, create a KMLLayer using the dataset.
  2. To create a KML layer from a portal item, create a PortalItem with a Portal and the KML portal item ID. Then, create a KMLLayer using the portal item.
  3. To create a KML layer from a local file, create a KMLDataset using the absolute file path to the local KML file. Then, create a KMLLayer using the dataset.
  4. Add the layer to the map with addOperationalLayer(_:).

Relevant API

  • KMLDataset
  • KMLLayer

Offline data

This sample uses the US State Capitals KML file. It is downloaded from ArcGIS Online automatically.

About the data

This sample displays three different KML files:

  • From URL: This is a map of the significant weather outlook produced by NOAA/NWS. It uses KML network links to always show the latest data.
  • From local file: This is a map of U.S. state capitals. It doesn't define an icon, so the default pushpin is used for the points.
  • From portal item: This is a map of U.S. states.

Tags

keyhole, KML, KMZ, OGC

Sample Code

AddKMLLayerView.swift
Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// Copyright 2024 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 AddKMLLayerView: View {
    /// The view model for the sample.
    @StateObject private var model = Model()

    /// The viewpoint used to update the map view.
    @State private var viewpoint: Viewpoint?

    /// The KML layer source selected by the picker.
    @State private var selectedLayerSource = KMLLayerSource.url

    var body: some View {
        MapView(map: model.map, viewpoint: viewpoint)
            .toolbar {
                ToolbarItem(placement: .bottomBar) {
                    Picker("KML Layer Source", selection: $selectedLayerSource) {
                        ForEach(KMLLayerSource.allCases, id: \.self) { source in
                            Text(source.label)
                        }
                    }
                    .onChange(of: selectedLayerSource, perform: setKMLLayer(forSource:))
                }
            }
            .task {
                // Loads all the KML layers when the sample opens.
                let kmlLayers = [model.urlLayer, model.localFileLayer, model.portalItemLayer]
                await kmlLayers.load()

                setKMLLayer(forSource: selectedLayerSource)
            }
    }

    /// Sets a KML layer on the map.
    /// - Parameter source: The source that was used to create the KML layer.
    private func setKMLLayer(forSource source: KMLLayerSource) {
        let kmlLayer = switch source {
        case .url: model.urlLayer
        case .localFile: model.localFileLayer
        case .portalItem: model.portalItemLayer
        }

        // Replaces the current KML layer on the map.
        model.map.removeAllOperationalLayers()
        model.map.addOperationalLayer(kmlLayer)

        // Zooms the map view's viewpoint to the layer.
        guard let layerExtent = kmlLayer.fullExtent else { return }
        let expandedExtent = layerExtent.withBuilder { $0.expand(by: 1.1) }
        viewpoint = Viewpoint(boundingGeometry: expandedExtent)
    }
}

private extension AddKMLLayerView {
    /// The view model that contains the map and KML layers.
    final class Model: ObservableObject {
        /// A map with a dark grey basemap.
        let map = Map(basemapStyle: .arcGISDarkGrayBase)

        /// A KML layer created from a web URL.
        let urlLayer: KMLLayer = {
            let url = URL(string: "https://www.wpc.ncep.noaa.gov/kml/noaa_chart/WPC_Day1_SigWx.kml")!
            let kmlDataset = KMLDataset(url: url)
            return KMLLayer(dataset: kmlDataset)
        }()

        /// A KML layer created from a local file in the bundle.
        let localFileLayer: KMLLayer = {
            let kmlDataset = KMLDataset(name: "US_State_Capitals", bundle: .main)!
            return KMLLayer(dataset: kmlDataset)
        }()

        /// A KML layer created from a portal item.
        let portalItemLayer: KMLLayer = {
            let portalID = PortalItem.ID("9fe0b1bfdcd64c83bd77ea0452c76253")!
            let portalItem = PortalItem(portal: .arcGISOnline(connection: .anonymous), id: portalID)
            return KMLLayer(item: portalItem)
        }()
    }

    /// A source that was used to create a KML layer.
    enum KMLLayerSource: CaseIterable {
        case url, localFile, portalItem

        /// A human-readable label for the KML layer source.
        var label: String {
            switch self {
            case .url: "URL"
            case .localFile: "Local File"
            case .portalItem: "Portal Item"
            }
        }
    }
}

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.