Filter features displayed on a map using a definition expression or a display filter.
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
Create an AGSServiceFeatureTable from a URL.
Create an AGSFeatureLayer from the service feature table.
Filter features on your feature layer using an AGSDefinitionExpression to view a subset of features and modify the attribute table.
Filter features on your feature layer using an AGSDisplayFilterDefinition to view a subset of features without modifying the attribute table.
Relevant API
AGSDefinitionExpression
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.
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
classDefinitionExpressionDisplayFilterViewController: UIViewController{
@IBOutletvar 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.staticlet 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.@IBActionfuncapplyDefinitionExpression() {
// Set the definition expression. displayFilterDefinition =nil definitionExpression ="req_Type = 'Tree Maintenance or Damage'" showFeatureCount()
}
/// Applies the display filter@IBActionfuncapplyFilter() {
definitionExpression =""// Create a display filter with a name and an SQL expression.guardlet 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.@IBActionfuncresetDefinitionExpression() {
definitionExpression ="" displayFilterDefinition =nil showFeatureCount()
}
/// Create a map and set its attributes.funcmakeMap() -> 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.funcshowFeatureCount() {
// 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) { [weakself] count, error inguardletself=selfelse { return }
iflet error = error {
self.presentAlert(error: error)
} else {
// Present the current feature count.self.presentAlert(title: "Current feature count", message: "\(count) features")
}
}
}
overridefuncviewDidLoad() {
super.viewDidLoad()
// Add the source code button item to the right of navigation bar. (self.navigationItem.rightBarButtonItem as?SourceCodeBarButtonItem)?.filenames = ["DefinitionExpressionDisplayFilterViewController"]
}
}