Find a route and directions

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.

Prerequisites

Before starting this tutorial:

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

  2. Your system meets the system requirements.

Steps

Get an access token

You need an access token to use the location services used in this tutorial.

  1. Go to the Create an API key tutorial to obtain an access token using your ArcGIS Location Platform or ArcGIS Online account.

  2. Ensure that the following privileges are enabled: Location services > Basemaps > Basemap styles service and Location services > Routing.

  3. Copy the access token as it will be used in the next step.

To learn more about other ways to get an access token, go to Types of authentication.

Open the Xcode project

  1. To start the tutorial, complete the Display a map tutorial or download and unzip the solution.

  2. Open the .xcodeproj file in Xcode.

  3. In Xcode, in the Project Navigator, click MainApp.swift.

  4. In the Editor, set the ArcGISEnvironment.apiKey property on the ArcGISEnvironment with your copied 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
        init() {
            ArcGISEnvironment.apiKey = APIKey("<#YOUR-ACCESS-TOKEN#>")
        }
    
    Expand

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
    69 70 71 72 73 74 75 76 77
    Change lineChange 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
    16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 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.

    ContentView.swift
    Use dark colors for code blocks
    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
    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
    20 21 22 23 24 25 26 27 28 29 30 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
    20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 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
    31 32 33 34 35 36 37 38 39 40 41
    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.

    ContentView.swift
    Use dark colors for code blocks
    37 38 39 40 41 42 43 44 45
    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.

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

    ContentView.swift
    Use dark colors for code blocks
    43 44 45 46 47 48 49
    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
    47 48 49 50 51 52
    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
    47 48 49 50 51 52 53 54 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
    53 54 55 56 57 58 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
    53 54 55 56 57 58 59 60 61 62 63 64 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
    69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 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
    86 87 88 89 90 91 92 93 94 95 96 97 98 99 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
    86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 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
    69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
    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
    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
    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
    109 110 111 112 113 114 115 116 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
    109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 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
    116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 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)
                        }
    
  6. Press Command + R to run the app.

The map should support two taps to create an origin and destination point and then use the route 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:

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.