Overview

You will learn: how to add feature layers to a 3D map.

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). Feature layers allow you to add datasets hosted online (with ArcGIS Online or other ArcGIS servers) or stored locally (in a runtime geodatabase, for example). By default, feature layers will draw with pre-set symbols to fill the extent of map, but you can customize this by setting your own styles with a renderer or using a SQL expression to limit the data retrieved.

In this lab you will create a new scene with an imagery basemap, add a feature layer that represents trails near Los Angeles, and display the scene in your app.

Before you begin

Reuse the starter project

Make a copy of the finished Create a starter app lab (or download here).

  • Open the .xcodeproj file in Xcode.

  • Run the project and verify the project builds and the map displays on the device simulator.

Steps

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 untill 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 Utilities Area. 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 a new scene with an imagery basemap

  1. Open ViewController.swift in the Project Navigator. Delete the map and map view related code in the viewDidLoad() method and use scene and sceneView instead.

    override func viewDidLoad() {
       super.viewDidLoad()
    
       /*** Change map/mapview to scene/sceneview ***/
       let scene = AGSScene(basemapType: .imageryWithLabels)
       sceneView.scene = scene
    }
    

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.

        ...
        override func viewDidLoad() {
            super.viewDidLoad()
    
            let scene = AGSScene(basemapType: .imageryWithLabels)
            sceneView.scene = scene
    
            /*** ADD ***/
            let trailsTable = AGSServiceFeatureTable(url: URL(string: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trails/FeatureServer/0")!)
            let trailsLayer = AGSFeatureLayer(featureTable: trailsTable)
            scene.operationalLayers.add(trailsLayer)
        }
        ...
    
  2. Set the initial display area (Viewpoint) of the map to the extent of features in the trails layer. Use the Camera to provide a specific perspective.

            let camera = AGSCamera(latitude: 33.950896, longitude: -118.525341, altitude: 16000.0, heading: 0, pitch: 50, roll: 0)
            sceneView.setViewpointCamera(camera)
    

Set the elevation source for the scene

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

            sceneView.scene = scene
    
            /*** ADD ***/
            let surface = AGSSurface()
            let elevationSource = AGSArcGISTiledElevationSource(url: URL(string: "https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer")!)
            surface.elevationSources.append(elevationSource)
            scene.baseSurface = surface
    
    
  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, the simulator does not provide good performance for interacting with the 3D scene. For best experience, run the app on a physical device.)

Congratulations, you're done!

Checkout and compare with our completed solution project.

Challenge

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:

  • Trail heads

    https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trailheads/FeatureServer

  • Parks and Open Spaces

    https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Parks_and_Open_Space/FeatureServer

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 trailsTable = AGSServiceFeatureTable(url: URL(string: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trails/FeatureServer/0")!)
     let trailsLayer = AGSFeatureLayer(featureTable: trailsTable)
     trailsLayer.definitionExpression = "ELEV_GAIN < 250"
     map.operationalLayers.add(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.