Delete features (feature service)

View on GitHub
Sample viewer app

Delete features from an online feature service.

Choose a feature to delete Confirm deletion

Use case

Sometimes users may want to delete features from an online feature service.

How to use the sample

Tap on a feature to display a callout. Tap on the trash can icon in the callout to delete the feature.

How it works

  1. Create an AGSServiceFeatureTable object from a URL.
  2. Create an AGSFeatureLayer object from the AGSServiceFeatureTable.
  3. Identify the selected feature by using AGSGeoView.identifyLayer(_:screenPoint:tolerance:returnPopupsOnly:maximumResults:completion:).
  4. Remove the selected features from the AGSServiceFeatureTable using AGSFeatureTable.delete(_:completion:).
  5. Update the table on the server using AGSServiceFeatureTable.applyEdits(completion:).

Relevant API

  • AGSFeature
  • AGSFeatureLayer
  • AGSServiceFeatureTable

Tags

deletion, feature, online, Service, table

Sample Code

DeleteFeaturesViewController.swift
                                                                                                                                
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
123
124
125
126
127
128
// 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 DeleteFeaturesViewController: UIViewController, AGSGeoViewTouchDelegate, AGSCalloutDelegate {
    @IBOutlet private var mapView: AGSMapView!

    private var featureTable: AGSServiceFeatureTable!
    private var featureLayer: AGSFeatureLayer!
    private var lastQuery: AGSCancelable!
    private var selectedFeature: AGSFeature!

    override func viewDidLoad() {
        super.viewDidLoad()

        // add the source code button item to the right of navigation bar
        (self.navigationItem.rightBarButtonItem as! SourceCodeBarButtonItem).filenames = ["DeleteFeaturesViewController"]

        // instantiate map with a basemap
        let map = AGSMap(basemapStyle: .arcGISStreets)

        // assign the map to the map view
        self.mapView.map = map
        self.mapView.setViewpoint(AGSViewpoint(center: AGSPoint(x: 544871.19, y: 6806138.66, spatialReference: .webMercator()), scale: 2e6))
        // set touch delegate on map view as self
        self.mapView.touchDelegate = self

        // instantiate service feature table using the url to the service
        featureTable = AGSServiceFeatureTable(url: URL(string: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/DamageAssessment/FeatureServer/0")!)
        // create a feature layer using the service feature table
        let featureLayer = AGSFeatureLayer(featureTable: self.featureTable)

        // add the feature layer to the operational layers on map
        map.operationalLayers.add(featureLayer)

        // store the feature layer for later use
        self.featureLayer = featureLayer
    }

    func showCallout(for feature: AGSFeature, at tapLocation: AGSPoint) {
        let title = feature.attributes["typdamage"] as! String
        self.mapView.callout.title = title
        self.mapView.callout.delegate = self
        self.mapView.callout.accessoryButtonImage = UIImage(named: "Discard")
        self.mapView.callout.show(for: feature, tapLocation: tapLocation, animated: true)
    }

    func deleteFeature(_ feature: AGSFeature) {
        self.featureTable.delete(feature) { [weak self] (error: Error?) in
            if let error = error {
                print("Error while deleting feature : \(error.localizedDescription)")
            } else {
                self?.applyEdits()
            }
        }
    }

    func applyEdits() {
        self.featureTable.applyEdits { (featureEditResults: [AGSFeatureEditResult]?, error: Error?) in
            if let error = error {
                self.presentAlert(message: "Error while applying edits :: \(error.localizedDescription)")
            } else {
                if let featureEditResults = featureEditResults,
                    featureEditResults.first?.completedWithErrors == false {
                    self.presentAlert(message: "Edits applied successfully")
                }
            }
        }
    }

    // MARK: - AGSGeoViewTouchDelegate

    func geoView(_ geoView: AGSGeoView, didTapAtScreenPoint screenPoint: CGPoint, mapPoint: AGSPoint) {
        if let lastQuery = self.lastQuery {
            lastQuery.cancel()
        }

        // hide the callout
        self.mapView.callout.dismiss()

        self.lastQuery = self.mapView.identifyLayer(self.featureLayer, screenPoint: screenPoint, tolerance: 12, returnPopupsOnly: false, maximumResults: 1) { [weak self] (identifyLayerResult: AGSIdentifyLayerResult) in
            if let error = identifyLayerResult.error {
                print(error)
            } else if let features = identifyLayerResult.geoElements as? [AGSFeature],
                let feature = features.first {
                // show callout for the first feature
                self?.showCallout(for: feature, at: mapPoint)
                // update selected feature
                self?.selectedFeature = feature
            }
        }
    }

    // MARK: - AGSCalloutDelegate

    func didTapAccessoryButton(for callout: AGSCallout) {
        // hide the callout
        self.mapView.callout.dismiss()

        // confirmation
        let alertController = UIAlertController(title: "Are you sure you want to delete the feature", message: nil, preferredStyle: .alert)
        // action for Yes
        let alertAction = UIAlertAction(title: "Yes", style: .default) { [weak self] (_) in
            self?.deleteFeature(self!.selectedFeature)
        }
        alertController.addAction(alertAction)

        // action for cancel
        let cancelAlertAction = UIAlertAction(title: "No", style: .cancel)
        alertController.addAction(cancelAlertAction)

        // present alert controller
        self.present(alertController, animated: true)
    }
}

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