Filter by definition expression or display filter

View on GitHub
Sample viewer app

Filter features displayed on a map using a definition expression or a display filter.

Map after applied expression

Use case

Definition queries allow you to define a subset of features to work with in a layer by filtering which features are retrieved from the dataset by the layer. This means that a definition query affects not only drawing, but also which features appear in the layer's attribute table and therefore which features can be selected, labeled, identified, and processed by geoprocessing tools.

Alternatively, display filters limit which features are drawn, but retain all features in queries and when processing. Definition queries and display filters can be used together on a layer, but definition queries limit the features available in the layer, while display filters only limit which features are displayed.

In this sample you can filter a dataset of tree quality selecting only those trees which require maintenance or are damaged.

How to use the sample

Use the toolbar to apply a definition expression to limit the features requested from the feature layer to those specified by a SQL query. This narrows down the results that are drawn, and removes those features from the layer's attribute table. Or, apply the display filter instead, to filter the results being drawn without modifying the attribute table. Tap "Reset" return the feature layer to its default state.

The feature count value shows the current number of features in the current map view extent. When a definition expression is applied to narrow down the list of features being drawn, the count is updated to reflect this change. However if a display filter is applied, the features which are not visible on the map will still be included in the total feature count.

How it works

  1. Create an AGSServiceFeatureTable from a URL.
  2. Create an AGSFeatureLayer from the service feature table.
  3. Filter features on your feature layer using an definition expression to view a subset of features and modify the attribute table.
  4. Filter features on your feature layer using an AGSDisplayFilterDefinition to view a subset of features without modifying the attribute table.

Relevant API

  • AGSFeatureLayer
  • AGSServiceFeatureTable

About the data

The feature service in this sample displays point features related to crime incidents such as graffiti and tree damage that have been reported by city residents.

Tags

definition expression, display filter, filter, limit data, query, restrict data, SQL, where clause

Sample Code

DefinitionExpressionDisplayFilterViewController.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
// 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
//
//   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 DefinitionExpressionDisplayFilterViewController: UIViewController {
    @IBOutlet var mapView: AGSMapView! {
        didSet {
            // Assign the map to the map view's map.
            mapView.map = makeMap()
        }
    }

    /// The URL to the feature service, tracking incidents in San Francisco.
    static let featureServiceURL = URL(string: "https://services2.arcgis.com/ZQgQTuoyBrtmoGdP/arcgis/rest/services/SF_311_Incidents/FeatureServer/0")!
    /// The feature layer made with the feature service URL.
    let featureLayer = AGSFeatureLayer(featureTable: AGSServiceFeatureTable(url: featureServiceURL))
    /// The display filter definition to apply to the feature layer.
    var displayFilterDefinition: AGSDisplayFilterDefinition?
    /// The definition expression to apply to the feature layer.
    var definitionExpression: String = ""

    /// Applies the definition expression.
    @IBAction func applyDefinitionExpression() {
        // Set the definition expression.
        displayFilterDefinition = nil
        definitionExpression = "req_Type = 'Tree Maintenance or Damage'"
        showFeatureCount()
    }

    /// Applies the display filter
    @IBAction func applyFilter() {
        definitionExpression = ""
        // Create a display filter with a name and an SQL expression.
        guard let damagedTrees = AGSDisplayFilter(name: "Damaged Trees", whereClause: "req_type LIKE '%Tree Maintenance%'") else { return }
        // Set the manual display filter definition using the display filter.
        let manualDisplayFilterDefinition = AGSManualDisplayFilterDefinition(activeFilter: damagedTrees, availableFilters: [damagedTrees])
        // Apply the display filter definition.
        displayFilterDefinition = manualDisplayFilterDefinition
        showFeatureCount()
    }

    /// Reset the definition expression.
    @IBAction func resetDefinitionExpression() {
        definitionExpression = ""
        displayFilterDefinition = nil
        showFeatureCount()
    }

    /// Create a map and set its attributes.
    func makeMap() -> AGSMap {
        // Initialize the map with the topographic basemap style.
        let map = AGSMap(basemapStyle: .arcGISTopographic)
        // Set the initial viewpoint.
        let viewpoint = AGSViewpoint(latitude: 37.772296660953138, longitude: -122.44014487516885, scale: 100_000)
        map.initialViewpoint = viewpoint
        // Add the feature layer to the map's operational layers.
        map.operationalLayers.add(featureLayer)
        return map
    }

    /// Count the features according to the applied expressions.
    func showFeatureCount() {
        // Set the extent to the current view.
        let extent = mapView.currentViewpoint(with: .boundingGeometry)?.targetGeometry.extent
        // Create the query parameters and set its geometry.
        let queryParameters = AGSQueryParameters()
        queryParameters.geometry = extent
        // Apply the expressions to the feature layer.
        featureLayer.displayFilterDefinition = displayFilterDefinition
        featureLayer.definitionExpression = definitionExpression
        // Query the feature count using the parameters.
        featureLayer.featureTable?.queryFeatureCount(with: queryParameters) { [weak self] count, error in
            guard let self = self else { return }
            if let error = error {
                self.presentAlert(error: error)
            } else {
                // Present the current feature count.
                self.presentAlert(title: "Current feature count", message: "\(count) features")
            }
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // Add the source code button item to the right of navigation bar.
        (self.navigationItem.rightBarButtonItem as? SourceCodeBarButtonItem)?.filenames = ["DefinitionExpressionDisplayFilterViewController"]
    }
}

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