Sketch on the map

View on GitHubSample viewer app

Use the Sketch Editor to edit or sketch a new point, line, or polygon geometry on a map.

Image of sketch on map 1 Image of sketch on map 2

Use case

A field worker could annotate features of interest on a map (via the GUI) such as location of dwellings (marked as points), geological features (polylines), or areas of glaciation (polygons).

How to use the sample

Tap the add button to choose a geometry for the Sketch Editor. Use the toolbar to undo or redo changes made to the sketch on the graphics overlay. The graphics overlay can be cleared using the clear all button.

How it works

  1. Create an AGSSketchEditor and set it to the map view's sketchEditor property.
  2. Use AGSSketchEditor.start(with:creationMode:) to start sketching. If editing an existing graphic's geometry, use AGSSketchEditor.start(with:).
  3. Check to see if undo and redo are possible during a sketch session with canUndo and canRedo using AGSSketchEditor.undoManager. If it's possible, use AGSSketchEditor.undoManager.undo() and AGSSketchEditor.undoManager.redo().
  4. To exit the sketch editor, use AGSSketchEditor.stop().

Relevant API

  • AGSGeometry
  • AGSGraphic
  • AGSGraphicsOverlay
  • AGSMapView
  • AGSSketchCreationMode
  • AGSSketchEditor

Tags

draw, edit

Sample Code

SketchViewController.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
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright 2016 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
//
//   http://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 UIKit
import ArcGIS

class SketchViewController: UIViewController {
    @IBOutlet var mapView: AGSMapView! {
        didSet {
            // Add the sketch editor to the map view.
            mapView.sketchEditor = sketchEditor

            // Start a default sketch editor with the polyline creation mode.
            sketchEditor.start(with: nil, creationMode: .polyline)

            // Set the map.
            mapView.map = AGSMap(basemapStyle: .arcGISLightGrayBase)
            // Set the viewpoint.
            mapView.setViewpoint(AGSViewpoint(targetExtent: AGSEnvelope(xMin: -10049589.670344, yMin: 3480099.843772, xMax: -10010071.251113, yMax: 3512023.489701, spatialReference: .webMercator())))
        }
    }
    @IBOutlet var addBarButtonItem: UIBarButtonItem!
    @IBOutlet var undoBarButtonItem: UIBarButtonItem!
    @IBOutlet var redoBarButtonItem: UIBarButtonItem!
    @IBOutlet var clearBarButtonItem: UIBarButtonItem!
    @IBOutlet var statusLabel: UILabel!

    /// The sketch editor to use on the map.
    let sketchEditor = AGSSketchEditor()
    /// An observer for the toolbar items.
    var barItemObserver: NSObjectProtocol!
    /// Key value pairs containing the creation modes and their titles.
    let creationModes: KeyValuePairs = [
        "Arrow": AGSSketchCreationMode.arrow,
        "Ellipse": .ellipse,
        "FreehandPolygon": .freehandPolygon,
        "FreehandPolyline": .freehandPolyline,
        "Multipoint": .multipoint,
        "Point": .point,
        "Polygon": .polygon,
        "Polyline": .polyline,
        "Rectangle": .rectangle,
        "Triangle": .triangle
    ]

    // MARK: - Actions

    @IBAction func addGeometryButtonTapped(_ sender: UIBarButtonItem) {
        // Create an alert controller for the action sheets.
        let alertController = UIAlertController(title: "Select a creation mode", message: nil, preferredStyle: .actionSheet)
        // Create an action for each creation mode and add it to the alert controller.
        creationModes.forEach { name, mode in
            let action = UIAlertAction(title: name, style: .default) { [weak self] _ in
                self?.statusLabel.text = "\(name) selected."
                self?.sketchEditor.start(with: nil, creationMode: mode)
            }
            alertController.addAction(action)
        }
        // Add "cancel" item.
        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
        alertController.addAction(cancelAction)

        // Present the action sheets when the add button is tapped.
        alertController.popoverPresentationController?.barButtonItem = addBarButtonItem
        present(alertController, animated: true)
    }

    @IBAction func undo() {
        // Check if there are actions to undo.
        guard sketchEditor.undoManager.canUndo else { return }
        sketchEditor.undoManager.undo()
    }

    @IBAction func redo() {
        // Check if there are actions to redo.
        guard sketchEditor.undoManager.canRedo else { return }
        sketchEditor.undoManager.redo()
    }

    @IBAction func clear() {
        self.sketchEditor.clearGeometry()
    }

    // MARK: - Views

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        // Add an observer to udate UI when needed.
        barItemObserver = NotificationCenter.default.addObserver(forName: .AGSSketchEditorGeometryDidChange, object: sketchEditor, queue: nil, using: { [unowned self] _ in
            // Enable/disable UI elements appropriately.
            undoBarButtonItem.isEnabled = sketchEditor.undoManager.canUndo
            redoBarButtonItem.isEnabled = sketchEditor.undoManager.canRedo
            clearBarButtonItem.isEnabled = sketchEditor.geometry.map { !$0.isEmpty } ?? false
        })
    }

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)

        if let observer = barItemObserver {
            // Remove the observer.
            NotificationCenter.default.removeObserver(observer)
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Add the source code button item to the right of navigation bar.
        (self.navigationItem.rightBarButtonItem as! SourceCodeBarButtonItem).filenames = ["SketchViewController"]
    }
}

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