Learn how to search for places of interest, such as hotels, cafes, and gas stations using 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 .

find places

Geocoding Geocoding is the process of converting text for an address or place to a complete address with a location. Learn more is the process of transforming an address or place name to a location on the earth’s surface. A 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 allows you to quickly find places that meet specific criteria.

In this tutorial, you use a picklist in the user interface to select a category of places, for example, coffee shops or gas stations. You locate all the places that match this category by accessing a geocoding service. The places are displayed on the map so that you can click on them to get further information.

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 search for places of interest, such as hotels, cafes, and gas stations 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 you 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 Find places tutorial requires the Geocoding privilege to find places 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. Create a private extension of ContentView and make a private class named Model of type ObservableObject. 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
    struct ContentView: View {
    @StateObject private var model = Model()
    @State private var map = {
    let map = Map(basemapStyle: .arcGISTopographic)
    map.initialViewpoint = Viewpoint(latitude: 34.02700, longitude: -118.80500, scale: 72_000)
    return map
    }()
    }
    private extension ContentView {
    private class Model: ObservableObject {
    }
    }
  3. 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()
    }
  4. Add the graphics overlay to the map view, wrap the map view inside a MapViewReader, and expose the MapViewProxy class in its closure. MapViewProxy provides operations that can be performed on the map view, such as ‘identify’. For more information see Perform GeoView operations.

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

Set up the LocatorTask

A locator task is used to search for places using a geocoding service. Results from this search contain the place location and additional information ( attributes Attributes are fields and values for a single feature or non-spatial record. They are typically stored in a database or service such as a feature service. Learn more ). Create the locator task along with any variables and methods needed to perform the search and display the results.

  1. In the Model, create a LocatorTask property named locator based on the Geocoding service.

    ContentView.swift
    private extension ContentView {
    private class Model: ObservableObject {
    let graphicsOverlay = GraphicsOverlay()
    let locator = LocatorTask(
    url: URL(string: "https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer")!
    )
    }
    }
  2. To support the geocode operation, create an enum named Category in the ContentView extension. Provide a String named “label” and a UIColor named “color”. Each category is searched using its label and is distinguished on the map using its associated color.

    ContentView.swift
    private extension ContentView {
    enum Category: CaseIterable, Equatable {
    case coffeeShop, gasStation, food, hotel, parksOutdoors
    var label: String {
    switch self {
    case .coffeeShop: return "Coffee shop"
    case .gasStation: return "Gas station"
    case .food: return "Food"
    case .hotel: return "Hotel"
    case .parksOutdoors: return "Parks and Outdoors"
    }
    }
    var color: UIColor {
    switch self {
    case .coffeeShop: return .brown
    case .gasStation: return .orange
    case .food: return .purple
    case .hotel: return .blue
    case .parksOutdoors: return .green
    }
    }
    }
    private class Model: ObservableObject {
    let graphicsOverlay = GraphicsOverlay()
    let locator = LocatorTask(
    url: URL(string: "https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer")!
    )
    }
    }
  3. In the ContentView struct, create a private variable named geoViewExtent of type Envelope with the @State property wrapper. This will be used to define the search location.

    ContentView.swift
    struct ContentView: View {
    @StateObject private var model = Model()
    @State private var geoViewExtent: Envelope?
    @State private var map = {
    let map = Map(basemapStyle: .arcGISTopographic)
    map.initialViewpoint = Viewpoint(latitude: 34.02700, longitude: -118.80500, scale: 72_000)
    return map
    }()
    var body: some View {
    MapViewReader { mapViewProxy in
    MapView(map: map, graphicsOverlays: [model.graphicsOverlay])
    }
    }
    }
  4. In the body, add the onVisibleAreaChanged(perform:) method to the map view. Set the geoViewExtent variable to the new visible area’s extent.

    ContentView.swift
    var body: some View {
    MapViewReader { mapViewProxy in
    MapView(map: map, graphicsOverlays: [model.graphicsOverlay])
    .onVisibleAreaChanged { newVisibleArea in
    geoViewExtent = newVisibleArea.extent
    }
    }
    }
  5. In the Model, create a private, asynchronous method called findPlaces(forCategory:searchPoint:) to perform the geocode Geocoding is the process of converting text for an address or place to a complete address with a location. Learn more search operation. The method takes a parameter of type Category that you created in the previous step to indicate which category of places to search for and a Point that acts as the preferred search location.

    ContentView.swift
    private class Model: ObservableObject {
    let graphicsOverlay = GraphicsOverlay()
    let locator = LocatorTask(
    url: URL(string: "https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer")!
    )
    func findPlaces(forCategory category: Category, searchPoint: Point? = nil) async {
    }
    }
  6. Clear the previous results by removing all graphics from the graphics overlay. Create and configure new GeocodeParameters. Populate them with the searchPoint parameter as the search location and add result attribute names.

    ContentView.swift
    func findPlaces(forCategory category: Category, searchPoint: Point? = nil) async {
    graphicsOverlay.removeAllGraphics()
    let geocodeParameters = GeocodeParameters()
    geocodeParameters.preferredSearchLocation = searchPoint
    geocodeParameters.addResultAttributeNames(["Place_addr", "PlaceName"])
    }
  7. Perform the search query using geocode(forSearchText:using:). Pass in the category’s label and the geocode parameters.

    ContentView.swift
    func findPlaces(forCategory category: Category, searchPoint: Point? = nil) async {
    graphicsOverlay.removeAllGraphics()
    let geocodeParameters = GeocodeParameters()
    geocodeParameters.preferredSearchLocation = searchPoint
    geocodeParameters.addResultAttributeNames(["Place_addr", "PlaceName"])
    do {
    let geocodeResults = try await locator.geocode(forSearchText: category.label, using: geocodeParameters)
    } catch {
    print(error)
    }
    }
  8. Create graphics for each of the results and add them to the graphics overlay.

    ContentView.swift
    func findPlaces(forCategory category: Category, searchPoint: Point? = nil) async {
    graphicsOverlay.removeAllGraphics()
    let geocodeParameters = GeocodeParameters()
    geocodeParameters.preferredSearchLocation = searchPoint
    geocodeParameters.addResultAttributeNames(["Place_addr", "PlaceName"])
    do {
    let geocodeResults = try await locator.geocode(forSearchText: category.label, using: geocodeParameters)
    if !geocodeResults.isEmpty {
    let placeSymbol = SimpleMarkerSymbol(
    style: .circle,
    color: category.color,
    size: 10
    )
    placeSymbol.outline = SimpleLineSymbol(
    style: .solid,
    color: .white,
    width: 2
    )
    let graphics = geocodeResults.map { Graphic(geometry: $0.displayLocation, attributes: $0.attributes, symbol: placeSymbol) }
    graphicsOverlay.addGraphics(graphics)
    }
    } catch {
    print(error)
    }
    }

Add a category picker

You will add a Picker to the user interface to show categories of places to find, for example, coffee shops or gas stations. Each category will be displayed with a different color on the map.

  1. In the ContentView struct, add a variable of type Category with the @State property wrapper and give it a default value of coffeeShop. This will indicate the currently selected category.

    ContentView.swift
    struct ContentView: View {
    @StateObject private var model = Model()
    @State private var geoViewExtent: Envelope?
    @State private var selectedCategory: Category = .coffeeShop
    @State private var map = {
    let map = Map(basemapStyle: .arcGISTopographic)
    map.initialViewpoint = Viewpoint(latitude: 34.02700, longitude: -118.80500, scale: 72_000)
    return map
    }()
  2. In the ContentView body, add a toolbar view modifier to the map view that places a Toolbar at the bottom of the view where the Picker will be contained.

    ContentView.swift
    var body: some View {
    MapViewReader { mapViewProxy in
    MapView(map: map, graphicsOverlays: [model.graphicsOverlay])
    .onVisibleAreaChanged { newVisibleArea in
    geoViewExtent = newVisibleArea.extent
    }
    .toolbar {
    ToolbarItemGroup(placement: .bottomBar) {
    }
    }
    }
    }
  3. Add a Picker to the toolbar and label it “Choose a category”. Set the selection to $selectedCategory. This will iterate through .allCases of Category to populate the Picker with all the category labels. Add the .labelsHidden modifier.

    ContentView.swift
    .toolbar {
    ToolbarItemGroup(placement: .bottomBar) {
    Picker("Choose a category", selection: $selectedCategory) {
    ForEach(Category.allCases, id: \.self) { category in
    Text(category.label)
    }
    }
    .labelsHidden()
    }
    }
  4. Lastly, add a .task modifier to the Picker that calls the model’s findPlaces(forCategory:searchPoint:) function. Pass in selectedCategory and the geoViewExtent?.center. This will initiate a geocode search when a category is selected.

    ContentView.swift
    .toolbar {
    ToolbarItemGroup(placement: .bottomBar) {
    Picker("Choose a category", selection: $selectedCategory) {
    ForEach(Category.allCases, id: \.self) { category in
    Text(category.label)
    }
    }
    .labelsHidden()
    .task(id: selectedCategory) {
    await model.findPlaces(forCategory: selectedCategory, searchPoint: geoViewExtent?.center)
    }
    }
    }

Show information about a tapped location in the map

An identify Identify is a query based on a point on a map or scene that is used to find feature, graphic, or raster cell data. Learn more operation can be used to get information about a geoelement A geoelement refers to any geographic element in a map or map view that can be identified by its location to return attribute information. Learn more (such 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 ) at a location where the user has tapped on the map. A callout A callout is a container view that can be added over the map and anchored to a coordinate with a leader. Learn more can be used to display this information.

  1. In the ContentView struct, add objects to track the map and screen locations. Create Point and CGPoint variables with the @State property wrappers. Name them mapLocation and tapLocation, respectively.

    ContentView.swift
    struct ContentView: View {
    @StateObject private var model = Model()
    @State private var geoViewExtent: Envelope?
    @State private var selectedCategory: Category = .coffeeShop
    @State private var tapLocation: CGPoint?
    @State private var mapLocation: Point?
    @State private var map = {
    let map = Map(basemapStyle: .arcGISTopographic)
    map.initialViewpoint = Viewpoint(latitude: 34.02700, longitude: -118.80500, scale: 72_000)
    return map
    }()
  2. Add objects to support the callout. Create CalloutPlacement and String variables with the @State property wrapper. Name them calloutPlacement and calloutText respectively.

    ContentView.swift
    struct ContentView: View {
    @StateObject private var model = Model()
    @State private var geoViewExtent: Envelope?
    @State private var selectedCategory: Category = .coffeeShop
    @State private var tapLocation: CGPoint?
    @State private var mapLocation: Point?
    @State private var calloutPlacement: CalloutPlacement?
    @State private var calloutText: String?
    @State private var map = {
    let map = Map(basemapStyle: .arcGISTopographic)
    map.initialViewpoint = Viewpoint(latitude: 34.02700, longitude: -118.80500, scale: 72_000)
    return map
    }()
  3. In the body, add a .callout modifier to the map view. Pass in $calloutPlacement as the placement parameter. In the closure, create a Text object using the calloutText and provide a default String in case it is nil.

    ContentView.swift
    var body: some View {
    MapViewReader { mapViewProxy in
    MapView(map: map, graphicsOverlays: [model.graphicsOverlay])
    .callout(placement: $calloutPlacement.animation(.default.speed(2))) { _ in
    Text(calloutText ?? "No address found.")
    .font(.callout)
    .padding(8)
    .frame(maxWidth: 350)
    }
    .onVisibleAreaChanged { newVisibleArea in
    geoViewExtent = newVisibleArea.extent
    }
    .toolbar {
    ToolbarItemGroup(placement: .bottomBar) {
    Picker("Choose a category", selection: $selectedCategory) {
    ForEach(Category.allCases, id: \.self) { category in
    Text(category.label)
    }
    }
    .labelsHidden()
    .task(id: selectedCategory) {
    await model.findPlaces(forCategory: selectedCategory, searchPoint: geoViewExtent?.center)
    }
    }
    }
    }
    }
  4. Add the onSingleTapGesture(perform:) method to the map view and set mapLocation and tapLocation.

    ContentView.swift
    var body: some View {
    MapViewReader { mapViewProxy in
    MapView(map: map, graphicsOverlays: [model.graphicsOverlay])
    .callout(placement: $calloutPlacement.animation(.default.speed(2))) { _ in
    Text(calloutText ?? "No address found.")
    .font(.callout)
    .padding(8)
    .frame(maxWidth: 350)
    }
    .onVisibleAreaChanged { newVisibleArea in
    geoViewExtent = newVisibleArea.extent
    }
    .onSingleTapGesture { screenPoint, mapPoint in
    tapLocation = screenPoint
    mapLocation = mapPoint
    }
    .toolbar {
    ToolbarItemGroup(placement: .bottomBar) {
    Picker("Choose a category", selection: $selectedCategory) {
    ForEach(Category.allCases, id: \.self) { category in
    Text(category.label)
    }
    }
    .labelsHidden()
    .task(id: selectedCategory) {
    await model.findPlaces(forCategory: selectedCategory, searchPoint: geoViewExtent?.center)
    }
    }
    }
    }
    }
  5. Add a .task modifier to the map view, passing in tapLocation as the idefntifier. Ensure that the location objects are not nil.

    ContentView.swift
    var body: some View {
    MapViewReader { mapViewProxy in
    MapView(map: map, graphicsOverlays: [model.graphicsOverlay])
    .callout(placement: $calloutPlacement.animation(.default.speed(2))) { _ in
    Text(calloutText ?? "No address found.")
    .font(.callout)
    .padding(8)
    .frame(maxWidth: 350)
    }
    .onVisibleAreaChanged { newVisibleArea in
    geoViewExtent = newVisibleArea.extent
    }
    .onSingleTapGesture { screenPoint, mapPoint in
    tapLocation = screenPoint
    mapLocation = mapPoint
    }
    .task(id: tapLocation) {
    guard let tapLocation, let mapLocation else { return }
    }
    .toolbar {
    ToolbarItemGroup(placement: .bottomBar) {
    Picker("Choose a category", selection: $selectedCategory) {
    ForEach(Category.allCases, id: \.self) { category in
    Text(category.label)
    }
    }
    .labelsHidden()
    .task(id: selectedCategory) {
    await model.findPlaces(forCategory: selectedCategory, searchPoint: geoViewExtent?.center)
    }
    }
    }
    }
    }
  6. Perform identify(on:screenPoint:tolerance:returnPopupsOnly:maximumResults:) on the map view proxy to identify the graphics at the tapLocation.

    ContentView.swift
    .task(id: tapLocation) {
    guard let tapLocation, let mapLocation else { return }
    do {
    let identifyResult = try await mapViewProxy.identify(
    on: model.graphicsOverlay,
    screenPoint: tapLocation,
    tolerance: 12
    )
    } catch {
    print(error)
    }
    }
  7. Lastly, assign the calloutText and calloutPlacement variables with with attributes from the first graphic of the identify results. This change in state will trigger the callout to be displayed.

    ContentView.swift
    .task(id: tapLocation) {
    guard let tapLocation, let mapLocation else { return }
    do {
    let identifyResult = try await mapViewProxy.identify(
    on: model.graphicsOverlay,
    screenPoint: tapLocation,
    tolerance: 12
    )
    if let graphic = identifyResult.graphics.first {
    let placeName = graphic.attributes["PlaceName"] as? String ?? "Unknown"
    let placeAddress = graphic.attributes["Place_addr"] as? String ?? "no address provided"
    calloutText = "\(placeName)\n\(placeAddress)"
    calloutPlacement = .location(mapLocation)
    } else {
    calloutPlacement = nil
    }
    } catch {
    print(error)
    }
    }

Run the solution

Press Command + R to run the app.

When the app opens, use the picker to search different categories of places in the Malibu area near Los Angeles, California. You can tap one of the places and see its name and address.

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.

When the app opens, use the picker to search different categories of places in the Malibu area near Los Angeles, California. You can tap one of the places and see its name and address.

What’s next?

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