Skip To Content ArcGIS for Developers Sign In Dashboard


You will learn: how to build an app that displays feature layers in a 3D scene.

With ArcGIS Runtime SDK for iOS, it's easy to create a mapping app that displays a basemap and one or more layers. ArcGIS Online hosts several tile and vector tile basemaps that you can use in your map (2D) or scene (3D), including streets, satellite, streets-vector, and streets-navigation-vector. You can also add your own datasets by adding feature layers. These layers are hosted by ArcGIS Online or by other ArcGIS servers. By default, feature layers will draw with pre-set symbols to fill the extent of map, but you can provide your own styles with a renderer. The feature layer data can also be controlled by defining a SQL expression to limit the data retrieved. Another common customization is to configure the popup to show specific information about the layer when you click on features in the map.

In this tutorial you will create a simple 3D scene with a satellite basemap, add a feature layer that represents trails near Los Angeles.

Before you begin

Make sure you have installed the latest version of Xcode.

Reuse the starter project

If you have completed the Create a starter app tutorial, then copy the project into a new empty folder. Otherwise, download and unzip the project solution. Open the .xcodeproj file in Xcode. Run and verify the map displays in the device simulator.


Modify the project to display a scene (3D) instead of a map (2D)

  1. Open Main.storyboard in the Project Navigator. Drill down the View Controller Scene tree hierarchy in the Outline View until you reach Map View. Click on the Map View node to select it, and then click on it again to rename it to Scene View.

  2. With the Scene View node selected, switch to the Identity inspector tab in the Inspectors panel. Change the class from AGSMapView to AGSSceneView.

  3. Open ViewController.swift in the Project Navigator. Change the map view outlet property declaration to scene view.

     /*** Change this ***/
     @IBOutlet weak var mapView: AGSMapView!
     /*** To this ***/
     @IBOutlet weak var sceneView: AGSSceneView!
  4. Switch back to Main.storyboard and right click on the yellow View Controller node in the Outline View. Disconnect the mapView outlet, and drag the sceneView outlet connector to the Scene View node to connect it.

Create an app configuration file

  1. Add a new swift file named AppConfiguration.swift. Use this file to specify constants that can be used by the app to connect to data and resources. Create two static URLs, one for the trails feature layer and a second for the Esri world elevation 3D source. We'll use these resources in future steps.

    extension URL {
        static let trailsLayer = URL(string: "")!
        static let elevationSource = URL(string: "")!

Create a new scene with an imagery basemap

  1. Open ViewController.swift in the Project Navigator. Remove the setupMap function completely and replace it with a new function named setupScene. Use this function to setup and configure your 3D scene. Create a new scene with the imagery basemap and assign it to the scene view.

    /** REPLACE **/
    private func setupScene() {        
        let scene = AGSScene(basemapType: .imageryWithLabels)
        sceneView.scene = scene
        /* code for next step will go here */
    override func viewDidLoad() {
        /** UPDATE **/

Set the elevation source for the scene

  1. Use the elevation service provided by Esri and add it to the scene.

        /* code from the previous step */
        scene.baseSurface = {
            let surface = AGSSurface()
            let elevationSource = AGSArcGISTiledElevationSource(url: .elevationSource)
            return surface
        /* code for next step will go here */

Add a new feature layer

  1. Create an AGSServiceFeatureTable to access the trails data and an AGSFeatureLayer to view it. Add the layer to the scene's operationalLayers.

        /* code from the previous step */
        let trailsLayer: AGSFeatureLayer = {
            let trailsTable = AGSServiceFeatureTable(url: .trailsLayer)
            let trailsLayer = AGSFeatureLayer(featureTable: trailsTable)
            return trailsLayer
        /* code for next step will go here */

Set a viewpoint camera for the scene

  1. Set the initial display area (Viewpoint) of the map to the extent of features in the trails layer. Use the AGSCamera to provide a specific perspective.

        /* code from the previous step */
        let camera = AGSCamera(
            latitude: 33.950896,
            longitude: -118.525341,
            altitude: 16000.0,
            heading: 0,
            pitch: 50,
            roll: 0
  2. Press Command-R to run the app in the iOS Simulator. When the app opens, you should see imagery of Los Angeles appear with trails displayed on top of the map with elevation in 3D.

    (Note, as of 100.8 Runtime supports Metal. In order to run your app in a simulator you must meet some minimum requirements. You must be developing on macOS Catalina, using Xcode 11, and simulating iOS 13.)

Congratulations, you're done!

The app should run and show trails displayed on top of a satellite basemap rendered in 3D. Compare your solution with our completed solution project.


Explore basemap

Visit the iOS SDK documentation to learn more about the different types of basemaps available. Try some different basemap types such as .lightGrayCanvas, .topographic or .nationalGeographic and pick your favorite basemap.

Add more layers

Try to add a few more park datasets into the scene. Here are a few suggestions:

Filter features

Sometimes you want your layer to show a subset of the data from a service. A definition expression lets you define attribute criteria using a SQL expression that restricts the features for a layer. Consult the service info for the Trails data source and construct an expression that limits the display to trails with an elevation gain of 250 meters or less.

    let lowElevationGainTrails: AGSFeatureLayer = {
        let trailsTable = AGSServiceFeatureTable(url: URL(string: "")!)
        let trailsLayer = AGSFeatureLayer(featureTable: trailsTable)
        trailsLayer.definitionExpression = "ELEV_GAIN < 250"
        return trailsLayer


Investigate the feature request mode

By default, an AGSServiceFeatureTable stores retrieved features using On Interaction Cache mode. See here and here for more details.

Depending on the nature of your data and your app, you might choose to use Interaction No Cache (to get data that changes often) or Manual Cache (to get small amounts of data regardless of the map view extent).

See here for how to populate the data in the case of Manual Cache.