List features related to the selected feature.

Use case
Related features are useful for managing relational information, like what you would store in a relational database management system (RDBMS). You can define relationship between records as one-to-one, one-to-many, or many-to-one. For example, you could model inspections and facilities as a many-to-one relationship. Then, for any facility feature, you could list related inspection features.
How to use the sample
Tap on a feature to select it, and the related features will be displayed in a list.
How it works
- With a
ArcGISFeature, callArcGISFeatureTable.queryRelatedFeatures(to:using:)on the feature’s feature table. - Iterate over the result’s collection of
RelatedFeatureQueryResultobjects to get the related features and add them to a list.
Relevant API
- ArcGISFeature
- ArcGISFeatureTable
- FeatureQueryResult
- RelatedFeatureQueryResult
Tags
features, identify, query, related, relationship, search
Sample code
QueryRelatedFeaturesView.swift
// 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 ArcGISimport SwiftUI
struct QueryRelatedFeaturesView: View { /// A map with a topographic basemap. @State private var map: Map = { let map = Map(basemapStyle: .arcGISTopographic)
// Creates and adds feature tables to the map to allow related feature querying. let preservesFeatureTable = ServiceFeatureTable( url: .alaskaParksFeatureServer.appending(component: "0") ) let speciesFeatureTable = ServiceFeatureTable( url: .alaskaParksFeatureServer.appending(component: "2") ) map.addTables([preservesFeatureTable, speciesFeatureTable])
return map }()
/// An "Alaska National Parks" feature layer. @State private var parksFeatureLayer = FeatureLayer( featureTable: ServiceFeatureTable( url: .alaskaParksFeatureServer.appending(component: "1") ) )
/// The text describing the loading status of the sample. @State private var loadingStatusText: String?
/// The point on the screen where the user tapped. @State private var tapPoint: CGPoint?
/// The results from querying related features. @State private var queryResults: RelatedFeatureQueryResults?
/// The error shown in the error alert. @State private var error: (any Error)?
var body: some View { MapViewReader { mapViewProxy in MapView(map: map) .onSingleTapGesture { screenPoint, _ in tapPoint = screenPoint } .task(id: tapPoint) { guard let tapPoint else { return } parksFeatureLayer.clearSelection()
do { // Identifies the tapped screen point. loadingStatusText = "Identifying feature" defer { loadingStatusText = nil }
let identifyResult = try await mapViewProxy.identify( on: parksFeatureLayer, screenPoint: tapPoint, tolerance: 12 )
// Selects the first feature in the result. guard let parkFeature = identifyResult.geoElements.first as? ArcGISFeature else { return } parksFeatureLayer.selectFeature(parkFeature)
// Queries for related features of the identified feature. loadingStatusText = "Querying related features"
let parksFeatureTable = parksFeatureLayer.featureTable as! ServiceFeatureTable let queryResults = try await parksFeatureTable.queryRelatedFeatures( to: parkFeature ) self.queryResults = RelatedFeatureQueryResults(results: queryResults) } catch { self.error = error } } .sheet( item: $queryResults, onDismiss: parksFeatureLayer.clearSelection ) { newQueryResults in RelatedFeaturesList(results: newQueryResults.results) .frame(idealWidth: 320, idealHeight: 380) } .overlay(alignment: .center) { // Shows a progress view when there is a loading status. if let loadingStatusText { VStack { Text(loadingStatusText) ProgressView() } .padding() .background(.ultraThickMaterial) .clipShape(.rect(cornerRadius: 10)) .shadow(radius: 50) } } .task { // Loads the parks feature layer and zooms the viewpoint to its extent. do { loadingStatusText = "Loading feature layer" defer { loadingStatusText = nil }
try await parksFeatureLayer.load() map.addOperationalLayer(parksFeatureLayer)
guard let parksLayerExtent = parksFeatureLayer.fullExtent else { return } await mapViewProxy.setViewpointGeometry(parksLayerExtent, padding: 20) } catch { self.error = error } } .errorAlert(presentingError: $error) } }}
private extension QueryRelatedFeaturesView { /// A list of features from given related feature query results. struct RelatedFeaturesList: View { /// The results to display in the list. let results: [RelatedFeatureQueryResult]
/// The action to dismiss the view. @Environment(\.dismiss) private var dismiss
var body: some View { NavigationStack { List { ForEach(Array(results.enumerated()), id: \.offset) { offset, result in let relatedTableName = result.relatedTable?.tableName Section(relatedTableName ?? "Feature Table \(offset + 1)") { ForEach(result.featureDisplayNames, id: \.self) { featureName in Text(featureName) } } } } .navigationTitle( results.first?.feature?.attributes["UNIT_NAME"] as? String ?? "Origin Feature" ) .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .confirmationAction) { Button("Done") { dismiss() } } } } } }
/// A struct containing the results from a related features query. struct RelatedFeatureQueryResults: Identifiable { /// A universally unique id to identify the type. let id = UUID() /// The related feature query results. let results: [RelatedFeatureQueryResult] }}
private extension RelatedFeatureQueryResult { /// The display names of the result's features. var featureDisplayNames: [String] { guard let displayFieldName = relatedTable?.layerInfo?.displayFieldName else { return [] } return features() .compactMap { $0.attributes[displayFieldName] as? String } .sorted() }}
private extension URL { /// The URL to the "Alaska National Parks Preserves Species" feature server. static var alaskaParksFeatureServer: URL { URL(string: "https://services2.arcgis.com/ZQgQTuoyBrtmoGdP/arcgis/rest/services/AlaskaNationalParksPreservesSpecies_List/FeatureServer")! }}
#Preview { QueryRelatedFeaturesView()}