Learn how to find an address or place with a search bar and the geocoding service A geocoding service is a service that can search for addresses, place addresses, businesses, reverse geocode coordinates to addresses, provide suggestions for places, and perform bulk geocoding. It is hosted by Esri as the ArcGIS Geocoding service and can also be hosted in ArcGIS Enterprise. Learn more .

Figure : Overview of how to search for an address

Geocoding is the process of converting address or place A place, also known as a point of interest (POI), is a location that represents a business, administrative entity, or geographic feature around the world. A place can also have attributes associated with it, such as a name, address, category, and ID. Learn more text into a location A location is a position or region (point, line, or polygon) on the earth's surface. Learn more . The geocoding service A geocoding service is a service that can search for addresses, place addresses, businesses, reverse geocode coordinates to addresses, provide suggestions for places, and perform bulk geocoding. It is hosted by Esri as the ArcGIS Geocoding service and can also be hosted in ArcGIS Enterprise. Learn more can search for an address or a place and perform reverse geocoding Reverse geocoding is the process of converting a point to its nearest address or place. Learn more .

In this tutorial, you use a search bar in the user interface to access the Geocoding service and search for addresses and places.

Prerequisites

Before starting this tutorial:

  1. You need an ArcGIS Location Platform or ArcGIS Online account.

  2. Your system meets the system requirements.

Set up authentication

To access the secure ArcGIS location services ArcGIS Location Services, also referred to as Location Services, are services hosted by Esri that provide geospatial functionality for developing mapping applications. They include the ArcGIS Basemap Styles service, ArcGIS Static Basemap Tiles service, ArcGIS Places service, ArcGIS Geocoding service, ArcGIS Routing service, ArcGIS GeoEnrichment service, and ArcGIS Elevation service. An ArcGIS Location Platform or ArcGIS Online account is required to use the services. Learn more used in this tutorial, you must implement API key authentication API key authentication is a type of authentication that uses an API key to authenticate requests to ArcGIS services and secure portal items. Learn more or user authentication User authentication is a type of authentication that allows users with an ArcGIS account to sign into an application and allow it to access ArcGIS content, services, and resources on their behalf. The typical authorization protocol used is OAuth2.0. Learn more using an ArcGIS Location Platform An ArcGIS Location Platform account, formerly known as an ArcGIS Developer account, is an identity associated with an ArcGIS Location Platform subscription. Learn more or an ArcGIS Online An ArcGIS Online account, also known as an ArcGIS Organization account, is an identity associated with an ArcGIS Online subscription. It can be used to access ArcGIS tools and develop applications with ArcGIS location services for an organization. Learn more account.

To complete this tutorial, click on the tab in the switcher below for your authentication type of choice, either API key authentication or User authentication.

Create a new API key access token An access token is an authorization string that provides access to secure ArcGIS content, data, and services. Its capabilities are determined by the privileges it supports. It is obtained by implementing API key authentication, User authentication, or App authentication. Learn more with privileges Privileges are a set of permissions assigned to ArcGIS accounts, developer credentials, and applications that grant access to secure resources and functionality in ArcGIS. Learn more to access the secure resources used in this tutorial.

  1. Complete the Create an API key tutorial and create an API key with the following privilege(s) Privileges are a set of permissions assigned to ArcGIS accounts, developer credentials, and applications that grant access to secure resources and functionality in ArcGIS. Learn more :

    • Privileges
      • Location services > Basemaps
      • Location services > Geocoding
  2. Copy and paste the API key access token into a safe location. It will be used in a later step.

Develop or Download

You have two options for completing this tutorial:

  1. Option 1: Develop the code or
  2. Option 2: Download the completed solution

Option 1: Develop the code

To start the tutorial, complete the Display a map tutorial. This creates a map to display the Santa Monica Mountains in California using the topographic basemap from the ArcGIS basemap styles service The ArcGIS Basemap Styles service, also referred to as the Basemap Styles service, is a location service that provides basemap styles and data for the world. It returns styles as Mapbox styles and web maps, and data as vector tiles and/or map tiles. It supports all of the styles in the ArcGIS Basemap style and Open Basemap style family. An ArcGIS Location Platform or ArcGIS Online account is required to use the service. Learn more .

Continue with the following instructions to add a search bar to the user interface and search for an address or place using the ArcGIS Geocoding service A geocoding service is a service that can search for addresses, place addresses, businesses, reverse geocode coordinates to addresses, provide suggestions for places, and perform bulk geocoding. It is hosted by Esri as the ArcGIS Geocoding service and can also be hosted in ArcGIS Enterprise. Learn more . First, you need to set the develop credentials in your app so that your app users can access the ArcGIS Geocoding service A geocoding service is a service that can search for addresses, place addresses, businesses, reverse geocode coordinates to addresses, provide suggestions for places, and perform bulk geocoding. It is hosted by Esri as the ArcGIS Geocoding service and can also be hosted in ArcGIS Enterprise. Learn more .

Set developer credentials

If you implemented API key authentication API key authentication is a type of authentication that uses an API key to authenticate requests to ArcGIS services and secure portal items. Learn more in the Display a map tutorial, the API key access token will only have the Basemaps privilege. The Search for an address tutorial requires the Geocoding privilege to search for an address using the LocatorTask. To create an API Key access token that has the Basemaps and Geocoding privileges, see the Set up authentication step and then follow the instructions below.

Pass your API Key access token to the ArcGISEnvironment.

  1. In the Project Navigator, click MainApp.swift.

  2. Set the ArcGISEnvironment.apiKey property with your API key access token.

    MainApp.swift
    ArcGISEnvironment.apiKey = APIKey("<#YOUR-ACCESS-TOKEN#>")

Best Practice: The access token is stored directly in the code as a convenience for this tutorial. Do not store credentials directly in source code in a production environment.

Update the map

  1. In Xcode, in the Project Navigator, click ContentView.swift.

  2. In the editor, change the map and viewpoint into two separate @State variables so that the viewpoint can be changed as the geocode results change.

    ContentView.swift
    struct ContentView: View {
    @State private var map = Map(basemapStyle: .arcGISImagery)
    @State private var viewpoint: Viewpoint? = Viewpoint(
    latitude: 34.02700,
    longitude: -118.80500,
    scale: 72_000
    )
  3. Create a private class named Model of type ObservableObject and add a @StateObject variable of the Model to the ContentView. See the programming patterns page for more information on how to manage states.

    ContentView.swift
    import SwiftUI
    import ArcGIS
    private class Model: ObservableObject {
    }
    struct ContentView: View {
    @StateObject private var model = Model()
    }
  4. Create a GraphicsOverlay named graphicsOverlay in the Model class. A graphics overlay A graphics overlay is a client-side, temporary container of graphics to display on a map view or scene view. Learn more is a container for graphics A graphic is a visual element composed of a geometry, symbol, and attributes that is displayed on a map or scene. Learn more .

    ContentView.swift
    private class Model: ObservableObject {
    let graphicsOverlay: GraphicsOverlay
    }
  5. Lastly, add the viewpoint and graphics overlay to the map view A map view is a user interface that displays map layers and graphics in 2D. It controls the area (extent) of the map that is visible and supports user interactions such as pan and zoom. Learn more .

    ContentView.swift
    var body: some View {
    MapView(map: map, viewpoint: viewpoint, graphicsOverlays: [model.graphicsOverlay])
    }

Add graphics

Graphics are added as a visual means to display the search result on the map A map is a collection of layers that are displayed in 2D. It is typically composed of a basemap layer and data layers. Learn more .

  1. Create a private property named textGraphic in the Model class. This graphic will be used to display the result’s text label.

    ContentView.swift
    19 collapsed lines
    // 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 SwiftUI
    import ArcGIS
    private class Model: ObservableObject {
    let graphicsOverlay: GraphicsOverlay
    let textGraphic: Graphic = {
    let textSymbol = TextSymbol(
    text: "",
    color: .black,
    size: 14,
    horizontalAlignment: .center,
    verticalAlignment: .bottom
    )
    textSymbol.backgroundColor = .white
    return Graphic(symbol: textSymbol)
    }()
    }
    19 collapsed lines
    struct ContentView: View {
    @StateObject private var model = Model()
    @State private var map = Map(basemapStyle: .arcGISImagery)
    @State private var viewpoint: Viewpoint? = Viewpoint(
    latitude: 34.02700,
    longitude: -118.80500,
    scale: 72_000
    )
    var body: some View {
    MapView(map: map, viewpoint: viewpoint, graphicsOverlays: [model.graphicsOverlay])
    }
    }
  2. Create a private property named markerGraphic in the Model class. This graphic will be used to display the result’s location.

    ContentView.swift
    19 collapsed lines
    // 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 SwiftUI
    import ArcGIS
    private class Model: ObservableObject {
    let graphicsOverlay: GraphicsOverlay
    let textGraphic: Graphic = {
    let textSymbol = TextSymbol(
    text: "",
    color: .black,
    size: 14,
    horizontalAlignment: .center,
    verticalAlignment: .bottom
    )
    textSymbol.backgroundColor = .white
    return Graphic(symbol: textSymbol)
    }()
    let markerGraphic: Graphic = {
    let markerSymbol = SimpleMarkerSymbol(
    style: .square,
    color: .red,
    size: 14
    )
    return Graphic(symbol: markerSymbol)
    }()
    }
    19 collapsed lines
    struct ContentView: View {
    @StateObject private var model = Model()
    @State private var map = Map(basemapStyle: .arcGISImagery)
    @State private var viewpoint: Viewpoint? = Viewpoint(
    latitude: 34.02700,
    longitude: -118.80500,
    scale: 72_000
    )
    var body: some View {
    MapView(map: map, viewpoint: viewpoint, graphicsOverlays: [model.graphicsOverlay])
    }
    }
  3. Create an init function for the Model class. Create a GraphicsOverlay with the textGraphic and markerGraphic and assign it to the model’s graphics overlay. This function will be called when Model is initialized.

    ContentView.swift
    19 collapsed lines
    // 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 SwiftUI
    import ArcGIS
    private class Model: ObservableObject {
    let graphicsOverlay: GraphicsOverlay
    let textGraphic: Graphic = {
    let textSymbol = TextSymbol(
    text: "",
    color: .black,
    size: 14,
    horizontalAlignment: .center,
    verticalAlignment: .bottom
    )
    textSymbol.backgroundColor = .white
    return Graphic(symbol: textSymbol)
    }()
    let markerGraphic: Graphic = {
    let markerSymbol = SimpleMarkerSymbol(
    style: .square,
    color: .red,
    size: 14
    )
    return Graphic(symbol: markerSymbol)
    }()
    init() {
    graphicsOverlay = GraphicsOverlay(graphics: [textGraphic, markerGraphic])
    }
    }
    19 collapsed lines
    struct ContentView: View {
    @StateObject private var model = Model()
    @State private var map = Map(basemapStyle: .arcGISImagery)
    @State private var viewpoint: Viewpoint? = Viewpoint(
    latitude: 34.02700,
    longitude: -118.80500,
    scale: 72_000
    )
    var body: some View {
    MapView(map: map, viewpoint: viewpoint, graphicsOverlays: [model.graphicsOverlay])
    }
    }

Create a locator task with geocode parameters

Geocoding is implemented with a locator A locator is an ArcGIS dataset that stores address information and the rules for translating descriptions of places (such as street addresses or place names) into spatial data that can be displayed on a map. Learn more , typically created by referencing a service such as the Geocoding service A geocoding service is a service that can search for addresses, place addresses, businesses, reverse geocode coordinates to addresses, provide suggestions for places, and perform bulk geocoding. It is hosted by Esri as the ArcGIS Geocoding service and can also be hosted in ArcGIS Enterprise. Learn more or, for offline geocoding, by referencing locator data contained in a mobile package A mobile package is a stand-alone Mobile Map Package (MMPK) or Mobile Scene Package (MSPK) file for use in offline applications built with ArcGIS Maps SDKs for Native Apps. Learn more . Geocoding parameters can be used to fine-tune the results, such as setting the maximum number of results or requesting additional attributes in the results.

  1. Create a LocatorTask property in the Model, named locator, based on the ArcGIS Geocoding service hosted by ESRI.

    ContentView.swift
    19 collapsed lines
    // 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 SwiftUI
    import ArcGIS
    private class Model: ObservableObject {
    let graphicsOverlay: GraphicsOverlay
    let locator = LocatorTask(
    url: URL(string: "https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer")!
    )
    let textGraphic: Graphic = {
    let textSymbol = TextSymbol(
    text: "",
    color: .black,
    size: 14,
    horizontalAlignment: .center,
    verticalAlignment: .bottom
    )
    textSymbol.backgroundColor = .white
    return Graphic(symbol: textSymbol)
    }()
    let markerGraphic: Graphic = {
    let markerSymbol = SimpleMarkerSymbol(
    style: .square,
    color: .red,
    size: 14
    )
    return Graphic(symbol: markerSymbol)
    }()
    init() {
    graphicsOverlay = GraphicsOverlay(graphics: [textGraphic, markerGraphic])
    }
    }
    19 collapsed lines
    struct ContentView: View {
    @StateObject private var model = Model()
    @State private var map = Map(basemapStyle: .arcGISImagery)
    @State private var viewpoint: Viewpoint? = Viewpoint(
    latitude: 34.02700,
    longitude: -118.80500,
    scale: 72_000
    )
    var body: some View {
    MapView(map: map, viewpoint: viewpoint, graphicsOverlays: [model.graphicsOverlay])
    }
    }
  2. In the ContentView, create a private String variable named searchText with the @State property wrapper. This will hold the user input and be used to perform the geocode operation.

    ContentView.swift
    54 collapsed lines
    // 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 SwiftUI
    import ArcGIS
    private class Model: ObservableObject {
    let graphicsOverlay: GraphicsOverlay
    let locator = LocatorTask(
    url: URL(string: "https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer")!
    )
    let textGraphic: Graphic = {
    let textSymbol = TextSymbol(
    text: "",
    color: .black,
    size: 14,
    horizontalAlignment: .center,
    verticalAlignment: .bottom
    )
    textSymbol.backgroundColor = .white
    return Graphic(symbol: textSymbol)
    }()
    let markerGraphic: Graphic = {
    let markerSymbol = SimpleMarkerSymbol(
    style: .square,
    color: .red,
    size: 14
    )
    return Graphic(symbol: markerSymbol)
    }()
    init() {
    graphicsOverlay = GraphicsOverlay(graphics: [textGraphic, markerGraphic])
    }
    }
    struct ContentView: View {
    @StateObject private var model = Model()
    @State private var map = Map(basemapStyle: .arcGISImagery)
    @State private var viewpoint: Viewpoint? = Viewpoint(
    latitude: 34.02700,
    longitude: -118.80500,
    scale: 72_000
    )
    @State private var searchText: String = ""
    var body: some View {
    MapView(map: map, viewpoint: viewpoint, graphicsOverlays: [model.graphicsOverlay])
    }
    }
  3. Create a private, asynchronous function named geocode(with:). This function will be called when the user inputs an address.

    ContentView.swift
    54 collapsed lines
    // 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 SwiftUI
    import ArcGIS
    private class Model: ObservableObject {
    let graphicsOverlay: GraphicsOverlay
    let locator = LocatorTask(
    url: URL(string: "https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer")!
    )
    let textGraphic: Graphic = {
    let textSymbol = TextSymbol(
    text: "",
    color: .black,
    size: 14,
    horizontalAlignment: .center,
    verticalAlignment: .bottom
    )
    textSymbol.backgroundColor = .white
    return Graphic(symbol: textSymbol)
    }()
    let markerGraphic: Graphic = {
    let markerSymbol = SimpleMarkerSymbol(
    style: .square,
    color: .red,
    size: 14
    )
    return Graphic(symbol: markerSymbol)
    }()
    init() {
    graphicsOverlay = GraphicsOverlay(graphics: [textGraphic, markerGraphic])
    }
    }
    struct ContentView: View {
    @StateObject private var model = Model()
    @State private var map = Map(basemapStyle: .arcGISImagery)
    @State private var viewpoint: Viewpoint? = Viewpoint(
    latitude: 34.02700,
    longitude: -118.80500,
    scale: 72_000
    )
    @State private var searchText: String = ""
    private func geocode(with searchText: String) async throws {
    }
    var body: some View {
    MapView(map: map, viewpoint: viewpoint, graphicsOverlays: [model.graphicsOverlay])
    }
    }
  4. Within the new function, create GeocodeParameters, and its attributes as follows:

    • Specify which attributes to return with addResultAttributeName. * is used to return all attributes.
    • Set the maximum number of results to be returned with maxResults. In this tutorial, only return the best match by passing in 1. Results are ordered by score, so just returning the first result will return the highest scoring result.
    • Set the spatial reference A spatial reference is a set of parameters, typically defined by a WKID, that define the coordinate system and spatial properties for geographic data. Applications use a spatial reference to correctly display the position of geographic data in a map or scene. Learn more with outputSpatialReference. By default the output spatial reference is determined by the geocode service. For optimal performance when displaying the geocode result, ensure the returned coordinates match those of the map view by providing mapView.spatialReference as a parameter.
    ContentView.swift
    67 collapsed lines
    // 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 SwiftUI
    import ArcGIS
    private class Model: ObservableObject {
    let graphicsOverlay: GraphicsOverlay
    let locator = LocatorTask(
    url: URL(string: "https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer")!
    )
    let textGraphic: Graphic = {
    let textSymbol = TextSymbol(
    text: "",
    color: .black,
    size: 14,
    horizontalAlignment: .center,
    verticalAlignment: .bottom
    )
    textSymbol.backgroundColor = .white
    return Graphic(symbol: textSymbol)
    }()
    let markerGraphic: Graphic = {
    let markerSymbol = SimpleMarkerSymbol(
    style: .square,
    color: .red,
    size: 14
    )
    return Graphic(symbol: markerSymbol)
    }()
    init() {
    graphicsOverlay = GraphicsOverlay(graphics: [textGraphic, markerGraphic])
    }
    }
    struct ContentView: View {
    @StateObject private var model = Model()
    @State private var map = Map(basemapStyle: .arcGISImagery)
    @State private var viewpoint: Viewpoint? = Viewpoint(
    latitude: 34.02700,
    longitude: -118.80500,
    scale: 72_000
    )
    @State private var searchText: String = ""
    private func geocode(with searchText: String) async throws {
    let parameters = GeocodeParameters()
    parameters.addResultAttributeName("*")
    parameters.maxResults = 1
    parameters.outputSpatialReference = map.spatialReference
    }
    8 collapsed lines
    var body: some View {
    MapView(map: map, viewpoint: viewpoint, graphicsOverlays: [model.graphicsOverlay])
    }
    }
  5. Perform the geocode operation by calling geocode(forSearchText:using:) and supplying the search text and the geocode parameters. The result obtained from the geocode operation will be displayed as a graphic A graphic is a visual element composed of a geometry, symbol, and attributes that is displayed on a map or scene. Learn more in the map view’s graphics overlay A graphics overlay is a client-side, temporary container of graphics to display on a map view or scene view. Learn more .

    ContentView.swift
    67 collapsed lines
    // 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 SwiftUI
    import ArcGIS
    private class Model: ObservableObject {
    let graphicsOverlay: GraphicsOverlay
    let locator = LocatorTask(
    url: URL(string: "https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer")!
    )
    let textGraphic: Graphic = {
    let textSymbol = TextSymbol(
    text: "",
    color: .black,
    size: 14,
    horizontalAlignment: .center,
    verticalAlignment: .bottom
    )
    textSymbol.backgroundColor = .white
    return Graphic(symbol: textSymbol)
    }()
    let markerGraphic: Graphic = {
    let markerSymbol = SimpleMarkerSymbol(
    style: .square,
    color: .red,
    size: 14
    )
    return Graphic(symbol: markerSymbol)
    }()
    init() {
    graphicsOverlay = GraphicsOverlay(graphics: [textGraphic, markerGraphic])
    }
    }
    struct ContentView: View {
    @StateObject private var model = Model()
    @State private var map = Map(basemapStyle: .arcGISImagery)
    @State private var viewpoint: Viewpoint? = Viewpoint(
    latitude: 34.02700,
    longitude: -118.80500,
    scale: 72_000
    )
    @State private var searchText: String = ""
    private func geocode(with searchText: String) async throws {
    let parameters = GeocodeParameters()
    parameters.addResultAttributeName("*")
    parameters.maxResults = 1
    parameters.outputSpatialReference = map.spatialReference
    let geocodeResults = try await model.locator.geocode(forSearchText: searchText, using: parameters)
    if let firstResult = geocodeResults.first,
    let extent = firstResult.extent,
    let location = firstResult.displayLocation,
    let symbol = model.textGraphic.symbol as? TextSymbol {
    viewpoint = Viewpoint(boundingGeometry: extent)
    model.markerGraphic.geometry = location
    model.textGraphic.geometry = location
    symbol.text = firstResult.label
    }
    }
    8 collapsed lines
    var body: some View {
    MapView(map: map, viewpoint: viewpoint, graphicsOverlays: [model.graphicsOverlay])
    }
    }

Add a search bar to the UI

To search an address using the application, add a UI element to prompt the user for text input.

  1. In the body, add an overlay to the MapView. Set the alignment to the top, add padding all around, and set the background.

    ContentView.swift
    87 collapsed lines
    // 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 SwiftUI
    import ArcGIS
    private class Model: ObservableObject {
    let graphicsOverlay: GraphicsOverlay
    let locator = LocatorTask(
    url: URL(string: "https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer")!
    )
    let textGraphic: Graphic = {
    let textSymbol = TextSymbol(
    text: "",
    color: .black,
    size: 14,
    horizontalAlignment: .center,
    verticalAlignment: .bottom
    )
    textSymbol.backgroundColor = .white
    return Graphic(symbol: textSymbol)
    }()
    let markerGraphic: Graphic = {
    let markerSymbol = SimpleMarkerSymbol(
    style: .square,
    color: .red,
    size: 14
    )
    return Graphic(symbol: markerSymbol)
    }()
    init() {
    graphicsOverlay = GraphicsOverlay(graphics: [textGraphic, markerGraphic])
    }
    }
    struct ContentView: View {
    @StateObject private var model = Model()
    @State private var map = Map(basemapStyle: .arcGISImagery)
    @State private var viewpoint: Viewpoint? = Viewpoint(
    latitude: 34.02700,
    longitude: -118.80500,
    scale: 72_000
    )
    @State private var searchText: String = ""
    private func geocode(with searchText: String) async throws {
    let parameters = GeocodeParameters()
    parameters.addResultAttributeName("*")
    parameters.maxResults = 1
    parameters.outputSpatialReference = map.spatialReference
    let geocodeResults = try await model.locator.geocode(forSearchText: searchText, using: parameters)
    if let firstResult = geocodeResults.first,
    let extent = firstResult.extent,
    let location = firstResult.displayLocation,
    let symbol = model.textGraphic.symbol as? TextSymbol {
    viewpoint = Viewpoint(boundingGeometry: extent)
    model.markerGraphic.geometry = location
    model.textGraphic.geometry = location
    symbol.text = firstResult.label
    }
    }
    var body: some View {
    MapView(map: map, viewpoint: viewpoint, graphicsOverlays: [model.graphicsOverlay])
    .overlay(alignment: .top) {
    .padding(EdgeInsets(top: 60, leading: 10, bottom: 10, trailing: 10))
    .background(.thinMaterial, ignoresSafeAreaEdges: .horizontal)
    }
    }
    2 collapsed lines
    }
  2. Within the overlay, add the following:

    • TextField: Pass in “Enter address” as the titleKey and the searchText variable as a binding for the text parameter
    • Spacer(): Add space in between the text field and button.
    • Button: Label it “Search” and using a Task method, call the geocode(with:) function and pass in searchText
    ContentView.swift
    87 collapsed lines
    // 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 SwiftUI
    import ArcGIS
    private class Model: ObservableObject {
    let graphicsOverlay: GraphicsOverlay
    let locator = LocatorTask(
    url: URL(string: "https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer")!
    )
    let textGraphic: Graphic = {
    let textSymbol = TextSymbol(
    text: "",
    color: .black,
    size: 14,
    horizontalAlignment: .center,
    verticalAlignment: .bottom
    )
    textSymbol.backgroundColor = .white
    return Graphic(symbol: textSymbol)
    }()
    let markerGraphic: Graphic = {
    let markerSymbol = SimpleMarkerSymbol(
    style: .square,
    color: .red,
    size: 14
    )
    return Graphic(symbol: markerSymbol)
    }()
    init() {
    graphicsOverlay = GraphicsOverlay(graphics: [textGraphic, markerGraphic])
    }
    }
    struct ContentView: View {
    @StateObject private var model = Model()
    @State private var map = Map(basemapStyle: .arcGISImagery)
    @State private var viewpoint: Viewpoint? = Viewpoint(
    latitude: 34.02700,
    longitude: -118.80500,
    scale: 72_000
    )
    @State private var searchText: String = ""
    private func geocode(with searchText: String) async throws {
    let parameters = GeocodeParameters()
    parameters.addResultAttributeName("*")
    parameters.maxResults = 1
    parameters.outputSpatialReference = map.spatialReference
    let geocodeResults = try await model.locator.geocode(forSearchText: searchText, using: parameters)
    if let firstResult = geocodeResults.first,
    let extent = firstResult.extent,
    let location = firstResult.displayLocation,
    let symbol = model.textGraphic.symbol as? TextSymbol {
    viewpoint = Viewpoint(boundingGeometry: extent)
    model.markerGraphic.geometry = location
    model.textGraphic.geometry = location
    symbol.text = firstResult.label
    }
    }
    var body: some View {
    MapView(map: map, viewpoint: viewpoint, graphicsOverlays: [model.graphicsOverlay])
    .overlay(alignment: .top) {
    HStack {
    TextField("Enter address", text: $searchText)
    Spacer()
    Button("Search") {
    Task {
    try await geocode(with: searchText)
    }
    }
    }
    .padding(EdgeInsets(top: 60, leading: 10, bottom: 10, trailing: 10))
    .background(.thinMaterial, ignoresSafeAreaEdges: .horizontal)
    }
    }
    2 collapsed lines
    }

Run the solution

Press Command + R to run the app.

You should see a search box at the top of the map. Search for an address by entering an address and tap the Search button. The result of the search should display on the map as a red square with the address displayed on top.

Alternatively, you can download the tutorial solution, as follows.

Option 2: Download the solution

  1. Click the Download solution link under Solution and unzip the file to a location on your machine.

  2. Open the .xcodeproj file in Xcode.

Since the downloaded solution does not contain authentication credentials, you must add the developer credentials that you created in the Set up authentication section.

Set developer credentials in the solution

To allow your app users to access ArcGIS location services ArcGIS Location Services, also referred to as Location Services, are services hosted by Esri that provide geospatial functionality for developing mapping applications. They include the ArcGIS Basemap Styles service, ArcGIS Static Basemap Tiles service, ArcGIS Places service, ArcGIS Geocoding service, ArcGIS Routing service, ArcGIS GeoEnrichment service, and ArcGIS Elevation service. An ArcGIS Location Platform or ArcGIS Online account is required to use the services. Learn more , use the developer credentials that you created in the Set up authentication step to authenticate requests for resources.

Pass your API Key access token to the ArcGISEnvironment.

  1. In the Project Navigator, click MainApp.swift.

  2. Set the AuthenticationMode to .apiKey.

    MainApp.swift
    // Change the `AuthenticationMode` to `.apiKey` if your application uses API key authentication.
    private var authenticationMode: AuthenticationMode { .apiKey }
  3. Set the apiKey property with your API key access token.

    MainApp.swift
    31 collapsed lines
    // 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
    //
    // 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 SwiftUI
    import ArcGIS
    import ArcGISToolkit
    @main
    struct MainApp: App {
    // The authentication mode.
    private enum AuthenticationMode {
    case apiKey
    case user
    }
    // Change the `AuthenticationMode` to `.apiKey` if your application uses API key authentication.
    private var authenticationMode: AuthenticationMode { .apiKey }
    // Please enter an API key access token if your application uses API key authentication.
    private let apiKey = APIKey("<#YOUR-ACCESS-TOKEN#>")
    43 collapsed lines
    // Setup an `Authenticator` with OAuth configuration if your application uses OAuth credentials.
    @ObservedObject var authenticator = Authenticator(
    oAuthUserConfigurations: [
    OAuthUserConfiguration(
    // Please enter OAuth credentials for user authentication.
    portalURL: URL(string: "<#YOUR-PORTAL-URL#>")!,
    clientID: "<#YOUR-CLIENT-ID#>",
    redirectURL: URL(string: "<#YOUR-REDIRECT-URL#>")!
    )
    ]
    )
    func setAuthentication() {
    switch authenticationMode {
    case .apiKey:
    ArcGISEnvironment.apiKey = apiKey
    case .user:
    ArcGISEnvironment.authenticationManager.arcGISAuthenticationChallengeHandler = authenticator
    }
    }
    init() {
    setAuthentication()
    }
    var body: some SwiftUI.Scene {
    WindowGroup {
    ContentView()
    .authenticator(authenticator)
    .ignoresSafeArea()
    }
    }
    }

Best Practice: The access token is stored directly in the code as a convenience for this tutorial. Do not store credentials directly in source code in a production environment.

Run the solution

Press Command + R to run the app.

You should see a search box at the top of the map. Search for an address by entering an address and tap the Search button. The result of the search should display on the map as a red square with the address displayed on top.

What’s next?

Learn how to use additional API features, ArcGIS location services, and ArcGIS tools in these tutorials: