A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://developers.arcgis.com/swift/route-and-directions/tutorials/find-a-route-and-directions/ below:

Find a route and directions | ArcGIS Maps SDK for Swift

Learn how to find a route and directions with the route service.

Overview of how to find a route and directions

Routing is the process of finding the path from an origin to a destination in a street network. You can use the Routing service to find routes, get driving directions, calculate drive times, and solve complicated, multiple vehicle routing problems. To create a route, you typically define a set of stops (origin and one or more destinations) and use the service to find a route with directions. You can also use a number of additional parameters such as barriers and mode of travel to refine the results.

In this tutorial, you define an origin and destination by clicking on the map. These values are used to get a route and directions from the route service. The directions are also displayed on the map.

Mapping and location services guide

For more background information about the topics in this tutorial, visit Routing and directions. To learn more about the service, visit Routing services.

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 used in this tutorial, you must implement API key authentication or user authentication using an ArcGIS Location Platform or an ArcGIS Online account.

You can implement API key authentication or user authentication in this tutorial. Compare the differences below:

API key authentication

Learn more in API key authentication.

User authentication

Learn more in User authentication.

Security and authentication guide

To learn more about the different types of authentication, visit Types of authentication.

Create a new API key access token with privileges 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):

  2. Copy and paste the API key access token into a safe location. It will be used in a later step.

Create new OAuth credentials to access the secure resources used in this tutorial.

  1. Complete the Create OAuth credentials for user authentication tutorial to obtain a Client ID and Redirect URL.

    A Client ID uniquely identifies your app on the authenticating server. If the server cannot find an app with the provided Client ID, it will not proceed with authentication.

    The Redirect URL (also referred to as a callback url) is used to identify a response from the authenticating server when the system returns control back to your app after an OAuth login. Since it does not necessarily represent a valid endpoint that a user could navigate to, the redirect URL can use a custom scheme, such as my-app://auth. It is important to make sure the redirect URL used in your app's code matches a redirect URL configured on the authenticating server.

  2. Copy and paste the Client ID and Redirect URL into a safe location. They will be used in a later step.

All users that access this application need account privileges to access the ArcGIS Basemap Styles service and the ArcGIS Routing service.

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.

Continue with the following instructions to find a route and directions with the ArcGIS Routing service. First, you need to set the develop credentials in your app so that your app users can access the ArcGIS Routing service.

Set developer credentials

If you implemented API key authentication in the Display a map tutorial, the API key access token will only have the Basemaps privilege. The Find a route and directions tutorial requires the Routing privilege to find a route using the RouteTask. To create an API Key access token that has the Basemaps and Routing 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

    Use dark colors for code blocks

    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
            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.

Use the Authenticator toolkit component to manage your OAuth credentials and pass it to the ArcGISEnvironment.

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

  2. Set your PortalURL, clientID and redirectURL values.

    MainApp.swift

    Use dark colors for code blocks

    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
            authenticator = Authenticator(oAuthUserConfigurations: [
                OAuthUserConfiguration(
    
                    portalURL: URL(string: "<#YOUR-PORTAL-URL#>")!,
                    clientID: ""<#YOUR-CLIENT-ID#>"",
                    redirectURL: URL(string: "<#YOUR-REDIRECT-URL#>")!
    
                )
            ])
            ArcGISEnvironment.authenticationManager.handleChallenges(using: authenticator)
    

Best Practice: The OAuth credentials are 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

A navigation basemap layer is typically used in routing applications. Update the basemap to use the .arcGISNavigation basemap style, and change the position of the map to center on Los Angeles.

  1. Update the Basemap style property from .arcGISTopographic to .arcGISNavigation and update the latitude and longitude coordinates to center on Los Angeles.

    ContentView.swift

    Use dark colors for code blocks

    68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 69 70 70 70 70 70 70 70 70 71 72 73 74 75 76 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77

    Change line Change line
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    struct ContentView: View {
    
        @State var map = {
    
            let map = Map(basemapStyle: .arcGISNavigation)
            map.initialViewpoint = Viewpoint(latitude: 34.05293, longitude: -118.24368, scale: 2e5)
    
            return map
        }()
    
  2. 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

    Use dark colors for code blocks

    15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 16 17 18 19 20 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 22 23 24 25 26 27 27 27 27 27 27 28 29 30 31 32 33 34 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 36

    Add line. Add line. Add line. Add line.
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    import SwiftUI
    
    import ArcGIS
    
    class Model: ObservableObject {
    
    }
    
    struct ContentView: View {
    
        @StateObject private var model = Model()
    
        @State var map = {
    
            let map = Map(basemapStyle: .arcGISNavigation)
            map.initialViewpoint = Viewpoint(latitude: 34.05293, longitude: -118.24368, scale: 2e5)
    
            return map
        }()
    
    }
Add graphics to the map view

A graphics overlay is a container for graphics. Graphics are added as a visual means to display the search result on the map.

  1. In the Model class, create a GraphicsOverlay named graphicsOverlay. In the ContentView, add the graphics overlay to the map view.

    A graphics overlay is a container for graphics. It is used with a map view to display graphics on a map. You can add more than one graphics overlay to a map view. Graphics overlays are displayed on top of all the other layers.

    ContentView.swift

    Use dark colors for code blocks

    15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 16 17 18 19 20 21 22 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 24 25 26 27 28 29 29 29 29 29 29 30 31 32 33 34 35 36 37 38 39 40 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 42 43 44

    Add line. Change line
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    import SwiftUI
    
    import ArcGIS
    
    class Model: ObservableObject {
    
        let graphicsOverlay = GraphicsOverlay()
    
    }
    
    struct ContentView: View {
    
        @StateObject private var model = Model()
    
        @State var map = {
    
            let map = Map(basemapStyle: .arcGISNavigation)
            map.initialViewpoint = Viewpoint(latitude: 34.05293, longitude: -118.24368, scale: 2e5)
    
            return map
        }()
    
        var body: some View {
    
            MapView(map: map, graphicsOverlays: [model.graphicsOverlay])
    
        }
    
    }
  2. Create a private Graphic property named startGraphic to the Model. Symbolize the graphic with a white circle and black outline. This graphic will be used to display the route's start location.

    ContentView.swift

    Use dark colors for code blocks

    19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 20 21 22 23 24 25 26 27 28 29 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31

    Add line. Add line. Add line. Add line. Add line. Add line.
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    class Model: ObservableObject {
    
        let graphicsOverlay = GraphicsOverlay()
    
        let startGraphic: Graphic = {
            let symbol = SimpleMarkerSymbol(style: .circle, color: .white, size: 8)
            symbol.outline = SimpleLineSymbol(style: .solid, color: .black, width: 1)
            let graphic = Graphic(symbol: symbol)
            return graphic
        }()
    
    }
    
  3. Create a private Graphic property named endGraphic. Symbolize the graphic with a black circle. This graphic will be used to display the route's end location.

    ContentView.swift

    Use dark colors for code blocks

    19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37

    Add line. Add line. Add line. Add line. Add line.
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    class Model: ObservableObject {
    
        let graphicsOverlay = GraphicsOverlay()
    
        let startGraphic: Graphic = {
            let symbol = SimpleMarkerSymbol(style: .circle, color: .white, size: 8)
            symbol.outline = SimpleLineSymbol(style: .solid, color: .black, width: 1)
            let graphic = Graphic(symbol: symbol)
            return graphic
        }()
    
        let endGraphic: Graphic = {
            let symbol = SimpleMarkerSymbol(style: .circle, color: .black, size: 9)
            let graphic = Graphic(symbol: symbol)
            return graphic
        }()
    
    }
    
  4. Create a private Graphic property named routeGraphic. Symbolize the graphic with a blue line. This graphic will be used to display the route line.

    ContentView.swift

    Use dark colors for code blocks

    30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 31 32 33 34 35 36 37 38 39 40 41 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17

    Add line. Add line. Add line. Add line. Add line.
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
        let endGraphic: Graphic = {
            let symbol = SimpleMarkerSymbol(style: .circle, color: .black, size: 9)
            let graphic = Graphic(symbol: symbol)
            return graphic
        }()
    
        let routeGraphic: Graphic = {
            let symbol = SimpleLineSymbol(style: .solid, color: .blue, width: 3)
            let graphic = Graphic(symbol: symbol)
            return graphic
        }()
    
  5. Create an init() method in the Model that adds startGraphic, endGraphic, and routeGraphic to the graphics overlay. This method will be called when Model is initialized.

    Because startGraphic, endGraphic, and routeGraphic haven't yet specified a Geometry, they will not be visible.

    ContentView.swift

    Use dark colors for code blocks

    36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 37 38 39 40 41 42 43 44 45 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25

    Add line. Add line. Add line.
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
        let routeGraphic: Graphic = {
            let symbol = SimpleLineSymbol(style: .solid, color: .blue, width: 3)
            let graphic = Graphic(symbol: symbol)
            return graphic
        }()
    
        init() {
            graphicsOverlay.addGraphics([routeGraphic, startGraphic, endGraphic])
        }
    
Create a route task and route parameters

A task makes a request to a service and returns the results. Use the RouteTask class to access a routing service.

A routing service with global coverage is part of ArcGIS location services. You can also publish custom routing services using ArcGIS Enterprise.

  1. Continuing in the Model, create a private RouteTask property named routeTask with the routing service.

    ContentView.swift

    Use dark colors for code blocks

    42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 43 44 45 46 47 48 49 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33

    Add line. Add line. Add line.
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
        init() {
            graphicsOverlay.addGraphics([routeGraphic, startGraphic, endGraphic])
        }
    
        private let routeTask = RouteTask(
            url: URL(string: "https://route-api.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World")!
        )
    
  2. Create a variable named directions defined as an array of DirectionManeuver objects. This will contain the step by step directions from the start to the end point.

    ContentView.swift

    Use dark colors for code blocks

    46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 47 48 49 50 51 52 52 52 52 52 52 52 52 52 52 52 52 52 52 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51

    Add line.
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
        private let routeTask = RouteTask(
            url: URL(string: "https://route-api.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World")!
        )
    
        var directions: [DirectionManeuver] = []
    
    
  3. Define a private, asynchronous function named solveRoute(start:end:) that takes a start and end Point. This method will be called when both the start and end points have been placed on the map.

    ContentView.swift

    Use dark colors for code blocks

    46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 47 48 49 50 51 52 53 54 54 54 54 54 54 54 54 54 54 54 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55

    Add line. Add line. Add line.
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
        private let routeTask = RouteTask(
            url: URL(string: "https://route-api.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World")!
        )
    
        var directions: [DirectionManeuver] = []
    
        func solveRoute(from start: Point, to end: Point) async throws {
    
        }
    
  4. Create default RouteParameters from the routeTask named routeParameters. Configure the parameters by setting two stops (the start and end points) and specify that directions are returned.

    ContentView.swift

    Use dark colors for code blocks

    52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 53 54 55 56 57 58 58 58 58 58 58 58 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59

    Add line. Add line. Add line.
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
        func solveRoute(from start: Point, to end: Point) async throws {
    
            let routeParameters = try await routeTask.makeDefaultParameters()
            routeParameters.returnsDirections = true
            routeParameters.setStops([Stop(point: start), Stop(point: end)])
    
        }
    
  5. Call the solveRoute(using:) function on the routeTask and pass in the routeParameters. To display the solved route, get the first route from the RouteResult and assign its geometry to routeGraphic. To display the directions, assign the directionManeuvers value from the first route to the directions variable.

    ContentView.swift

    Use dark colors for code blocks

    52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 53 54 55 56 57 58 59 60 61 62 63 64 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65

    Add line. Add line. Add line. Add line. Add line.
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
        func solveRoute(from start: Point, to end: Point) async throws {
    
            let routeParameters = try await routeTask.makeDefaultParameters()
            routeParameters.returnsDirections = true
            routeParameters.setStops([Stop(point: start), Stop(point: end)])
    
            let routeResult = try await routeTask.solveRoute(using: routeParameters)
            if let firstRoute = routeResult.routes.first {
                routeGraphic.geometry = firstRoute.geometry
                directions = firstRoute.directionManeuvers
            }
    
        }
    
Handle map view touch events

The app will use locations derived from a user tapping the map view to generate the stops on a route. Configure the view to handle touch events from the map view. The locations derived from a user tapping the map view will be used to generate routes in a later step.

  1. In the ContentView struct, create two @State private variables of type Point named startPoint and endPoint. These will contain the start and end locations of the route.

    ContentView.swift

    Use dark colors for code blocks

    68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 69 70 71 72 72 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 88 89 90

    Add line. Add line.
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    struct ContentView: View {
    
        @StateObject private var model = Model()
    
        @State private var startPoint: Point?
        @State private var endPoint: Point?
    
        @State var map = {
    
            let map = Map(basemapStyle: .arcGISNavigation)
            map.initialViewpoint = Viewpoint(latitude: 34.05293, longitude: -118.24368, scale: 2e5)
    
            return map
        }()
    
        var body: some View {
    
            MapView(map: map, graphicsOverlays: [model.graphicsOverlay])
    
        }
    
    }
  2. Add the onSingleTapGesture method to the map view. If it is the user's first tap, set the startPoint to the current mapPoint. Otherwise, set the endPoint to the current mapPoint. Assign the geometries for startGraphic and endGraphic accordingly.

    ContentView.swift

    Use dark colors for code blocks

    85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 100 100 100

    Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line.
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
        var body: some View {
    
            MapView(map: map, graphicsOverlays: [model.graphicsOverlay])
    
                .onSingleTapGesture { _, mapPoint in
                    if startPoint == nil {
                        startPoint = mapPoint
                        model.startGraphic.geometry = startPoint
                    } else {
                        endPoint = mapPoint
                        model.endGraphic.geometry = endPoint
                    }
                }
    
        }
    
  3. Add a .task modifier to the map view with endPoint as an identifier. This task is called if the value of endPoint changes. Ensure that the start and end points are not nil and pass them into the model's solveRoute(start:end:) method. This attempts to solve the route using the start and end points.

    ContentView.swift

    Use dark colors for code blocks

    85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 109 109 109

    Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line.
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
        var body: some View {
    
            MapView(map: map, graphicsOverlays: [model.graphicsOverlay])
    
                .onSingleTapGesture { _, mapPoint in
                    if startPoint == nil {
                        startPoint = mapPoint
                        model.startGraphic.geometry = startPoint
                    } else {
                        endPoint = mapPoint
                        model.endGraphic.geometry = endPoint
                    }
                }
    
                .task(id: endPoint) {
                    guard let startPoint = startPoint, let endPoint = endPoint else { return }
                    do {
                        try await model.solveRoute(from: startPoint, to: endPoint)
                    } catch {
                        print(error)
                    }
                }
    
        }
    
Add a UI to display driving directions

To display the turn-by-turn directions from the route, some UI element is required.

  1. In the ContentView struct, add a Bool variable named isShowingDirections to indicate if the directions are shown or not. Set its initial value to false.

    ContentView.swift

    Use dark colors for code blocks

    68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 83 82 81 79 77 75 73 71 69 67 65 63 61 59 57 55 53 51 49 47 45 43 41 39 37 35 33 31 30 29 28 28 28 28

    Add line.
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    struct ContentView: View {
    
        @StateObject private var model = Model()
    
        @State private var isShowingDirections = false
    
        @State private var startPoint: Point?
        @State private var endPoint: Point?
    
        @State var map = {
    
            let map = Map(basemapStyle: .arcGISNavigation)
            map.initialViewpoint = Viewpoint(latitude: 34.05293, longitude: -118.24368, scale: 2e5)
    
            return map
        }()
    
  2. Add a .toolbar and ToolbarItemGroup to the bottom of the map view.

    ContentView.swift

    Use dark colors for code blocks

    85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 112 113 114 115 115 115

    Add line. Add line. Add line. Add line. Add line.
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
        var body: some View {
    
            MapView(map: map, graphicsOverlays: [model.graphicsOverlay])
    
                .onSingleTapGesture { _, mapPoint in
                    if startPoint == nil {
                        startPoint = mapPoint
                        model.startGraphic.geometry = startPoint
                    } else {
                        endPoint = mapPoint
                        model.endGraphic.geometry = endPoint
                    }
                }
    
                .task(id: endPoint) {
                    guard let startPoint = startPoint, let endPoint = endPoint else { return }
                    do {
                        try await model.solveRoute(from: startPoint, to: endPoint)
                    } catch {
                        print(error)
                    }
                }
    
                .toolbar {
                    ToolbarItemGroup(placement: .bottomBar) {
    
                    }
                }
    
        }
    
  3. Add a Button, labeled "Show directions", to the toolbar. This button indicates that the user wants to show the directions so toggle the isShowingDirections value to true.

    ContentView.swift

    Use dark colors for code blocks

    108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 109 110 111 112 113 114 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 116 117 117 117 117 117

    Add line. Add line. Add line.
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
                .toolbar {
                    ToolbarItemGroup(placement: .bottomBar) {
    
                        Button("Show directions") {
                            isShowingDirections = true
                        }
    
                    }
                }
    
  4. Add a .popover with a NavigationView to the toolbar. Set the popover's isPresented parameter to isShowingDirections. The popover will display according to the isShowingDirections value. Customize the navigation view.

    ContentView.swift

    Use dark colors for code blocks

    108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 109 110 111 112 113 114 115 116 117 118 118 118 118 118 118 118 118 118 118 118 118 118 118 119 120 121 122 123 124 125 125 125 125 125

    Add line. Add line. Add line. Add line. Add line. Add line. Add line.
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
                .toolbar {
                    ToolbarItemGroup(placement: .bottomBar) {
    
                        Button("Show directions") {
                            isShowingDirections = true
                        }
    
                        .popover(isPresented: $isShowingDirections) {
                            NavigationView {
    
                            }
                            .navigationViewStyle(.stack)
                            .frame(idealWidth: 320, idealHeight: 428)
                        }
    
                    }
                }
    
  5. Within the NavigationView content, create a List with directions which contains an array of DirectionManeuver objects. Configure the navigation view with a title, display mode, and "Done" button. When the button is tapped, isShowingDirections is set to false which closes the popover.

    ContentView.swift

    Use dark colors for code blocks

    115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 135 135 135 135 135 135 135

    Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line.
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
                        .popover(isPresented: $isShowingDirections) {
                            NavigationView {
    
                                List(model.directions, id: \.text) { directionManeuver in
                                    Text(directionManeuver.text)
                                }
                                .navigationTitle("Directions")
                                .navigationBarTitleDisplayMode(.inline)
                                .toolbar {
                                    ToolbarItem(placement: .confirmationAction) {
                                        Button("Done") {
                                            isShowingDirections = false
                                        }
                                    }
                                }
    
                            }
                            .navigationViewStyle(.stack)
                            .frame(idealWidth: 320, idealHeight: 428)
                        }
    
Run the solution

Press Command + R to run the app.

If you are using the Xcode simulator your system must meet these minimum requirements: macOS 14 (Sonoma), Xcode 16, iOS 18. If you are using a physical device, then refer to the system requirements.

The map should support two taps to create an origin and destination point and then use the ArcGIS Routing service to display the resulting route.

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, 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

    Use dark colors for code blocks

    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
        // 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

    Expand

    Use dark colors for code blocks
    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
        // Please enter an API key access token if your application uses API key authentication.
    
        private let 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.

Use the Authenticator toolkit component to manage your OAuth credentials and pass it to the ArcGISEnvironment.

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

  2. Set the AuthenticationMode to .user.

    MainApp.swift

    Use dark colors for code blocks

    1
    2
    3
    // Change the `AuthenticationMode` to `.user` if your application uses OAuth credentials.
    
    private var authenticationMode: AuthenticationMode { .user }
  3. Set your portalURL, clientID and redirectURL values.

    MainApp.swift

    Expand

    Use dark colors for code blocks
    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
        // 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#>")!
    
                )
            ]
        )
    

Best Practice: The OAuth credentials are 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.

If you are using the Xcode simulator your system must meet these minimum requirements: macOS 14 (Sonoma), Xcode 16, iOS 18. If you are using a physical device, then refer to the system requirements.

The map should support two taps to create an origin and destination point and then use the ArcGIS Routing service to display the resulting route.

What's next?

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


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4