Learn how to apply renderers A renderer is a collection of rules and symbols used to display the data in a layer. Learn more and label definitions to a feature layer A feature layer (client-side) is a data layer that can access and display features from a feature service that has the same type of geometry and attribute fields. Learn more based on attribute values.

style a feature layer

Applications can display feature layer data with different styles to enhance the visualization. The type of Renderer you choose depends on your application. A SimpleRenderer applies the same symbol to all features, a UniqueValueRenderer applies a different symbol to each unique attribute value, and a ClassBreaksRenderer applies a symbol to a range of numeric values. Renderers are responsible for accessing the data and applying the appropriate symbol to each feature when the layer draws. You can also use a LabelDefinition to show attribute information for features. Visit the Styles and data visualization documentation to learn more about styling layers.

You can also author, style and save web maps, web scenes, and layers as portal items and then add them to the map in your application. Visit the following tutorials to learn more about adding portal items.

In this tutorial, you will apply different renderers A renderer is a collection of rules and symbols used to display the data in a layer. Learn more to enhance the visualization of three feature layers with data for the Santa Monica Mountains: Trailheads with a single symbol, Trails based on elevation change and bike use, and Parks and Open Spaces based on the type of park.

Prerequisites

Before starting this tutorial:

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

  2. Your system meets the system requirements.

Develop or Download

You have two options for completing this tutorial:

  1. Option 1: Develop the code or
  2. Option 2: Download the completed solution

Option 1: Develop the code

To start the tutorial, complete the Display a map tutorial. This creates a map to display the Santa Monica Mountains in California using the topographic basemap from the ArcGIS Basemap Styles service The ArcGIS Basemap Styles service, also referred to as the Basemap Styles service, is a location service that provides basemap styles and data for the world. It returns styles as Mapbox styles and web maps, and data as vector tiles and/or map tiles. It supports all of the styles in the ArcGIS Basemap style and Open Basemap style family. An ArcGIS Location Platform or ArcGIS Online account is required to use the service. Learn more .

Open an Xcode project

  1. Open the .xcodeproj project you created by completing the Display a map tutorial.
  2. Continue with the following instructions to apply renderers and label definitions to a feature layer based on attribute values.

Add app configuration constants

Create a configuration file to specify constants that can be used by the app to connect to data and resources.

  1. Add a new swift file named AppConfiguration.swift.

  2. Create five static URLs: four for accessing feature layers, and a fifth for accessing a static image for use in a picture marker symbol. You will use these resources in future steps.

    AppConfiguration.swift
    extension URL {
    static let bikesTrails = URL(string: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trails/FeatureServer/0")!
    static let parksAndOpenSpaces = URL(string: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Parks_and_Open_Space/FeatureServer/0")!
    static let trails = URL(string: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trails/FeatureServer/0")!
    static let trailheads = URL(string: "https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trailheads/FeatureServer/0")!
    static let trailheadImage = URL(string: "https://static.arcgis.com/images/Symbols/NPS/npsPictograph_0231b.png")!
    }

Create helper method to make a feature layer

Add a helper method that creates a feature layer from a given URL.

  1. Open ContentView.swift in the Project Navigator. Add a new method named makeFeatureLayer(url: URL).

    ContentView.swift
    private func makeFeatureLayer(url: URL) -> FeatureLayer {
    let serviceFeatureTable = ServiceFeatureTable(url: url)
    let featureLayer = FeatureLayer(featureTable: serviceFeatureTable)
    return featureLayer
    }

Add a layer with a unique value renderer

Create a method to apply a different symbol for each type of park area to the Parks and Open Spaces feature layer.

  1. Add a new method named makeOpenSpaceLayer() in ContentView.swift.

    ContentView.swift
    private func makeOpenSpaceLayer() {
    // Creates a parks and open spaces feature layer.
    let featureLayer = makeFeatureLayer(url: .parksAndOpenSpaces)
    // Creates fill symbols.
    let purpleFillSymbol = SimpleFillSymbol(style: .solid, color: .purple, outline: .none)
    let greenFillSymbol = SimpleFillSymbol(style: .solid, color: .green, outline: .none)
    let blueFillSymbol = SimpleFillSymbol(style: .solid, color: .blue, outline: .none)
    let redFillSymbol = SimpleFillSymbol(style: .solid, color: .red, outline: .none)
    // Creates a unique value for natural areas, regional open spaces, local parks & regional recreation parks.
    let naturalAreas = UniqueValue(description: "Natural Areas", label: "Natural Areas", symbol: purpleFillSymbol, values: ["Natural Areas"])
    let regionalOpenSpace = UniqueValue(description: "Regional Open Space", label: "Regional Open Space", symbol: greenFillSymbol, values: ["Regional Open Space"])
    let localPark = UniqueValue(description: "Local Park", label: "Local Park", symbol: blueFillSymbol, values: ["Local Park"])
    let regionalRecreationPark = UniqueValue(description: "Regional Recreation Park", label: "Regional Recreation Park", symbol: redFillSymbol, values: ["Regional Recreation Park"])
    // Creates and assigns a unique value renderer to the feature layer.
    let openSpacesUniqueValueRenderer = UniqueValueRenderer(fieldNames: ["TYPE"], uniqueValues: [naturalAreas, regionalOpenSpace, localPark, regionalRecreationPark], defaultLabel: "Open Spaces", defaultSymbol: .none)
    featureLayer.renderer = openSpacesUniqueValueRenderer
    // Sets the layer opacity to semi-transparent.
    featureLayer.opacity = 0.2
    // Adds the feature layer to the map.
    map.addOperationalLayer(featureLayer)
    }
  2. Update the MapView task to call the new makeOpenSpaceLayer() method.

    ContentView.swift
    // Displays the map.
    MapView(map: map)
    .task {
    makeOpenSpaceLayer()
    }
  3. Press Command + R to run the app.

When the app opens, Parks and Open Spaces feature layer is added to the map. The map displays the different types of parks and open spaces with four unique symbols.

Add a layer with a class breaks renderer

Create a method to apply a different symbol for each of the five ranges of elevation gain to the Trails feature layer.

  1. Add a new method named addTrailsLayer().

    ContentView.swift
    private func addTrailsLayer() {
    // Creates a trails feature layer.
    let featureLayer = makeFeatureLayer(url: .trails)
    // Creates simple line symbols.
    let firstClassSymbol = SimpleLineSymbol(style: .solid, color: .purple, width: 3.0)
    let secondClassSymbol = SimpleLineSymbol(style: .solid, color: .purple, width: 4.0)
    let thirdClassSymbol = SimpleLineSymbol(style: .solid, color: .purple, width: 5.0)
    let fourthClassSymbol = SimpleLineSymbol(style: .solid, color: .purple, width: 6.0)
    let fifthClassSymbol = SimpleLineSymbol(style: .solid, color: .purple, width: 7.0)
    // Creates 5 class breaks.
    let firstClassBreak = ClassBreak(description: "Under 500", label: "0 - 500", minValue: 0.0, maxValue: 500.0, symbol: firstClassSymbol)
    let secondClassBreak = ClassBreak(description: "501 to 1000", label: "501 - 1000", minValue: 501.0, maxValue: 1000.0, symbol: secondClassSymbol)
    let thirdClassBreak = ClassBreak(description: "1001 to 1500", label: "1001 - 1500", minValue: 1001.0, maxValue: 1500.0, symbol: thirdClassSymbol)
    let fourthClassBreak = ClassBreak(description: "1501 to 2000", label: "1501 - 2000", minValue: 1501.0, maxValue: 2000.0, symbol: fourthClassSymbol)
    let fifthClassBreak = ClassBreak(description: "2001 to 2300", label: "2001 - 2300", minValue: 2001.0, maxValue: 2300.0, symbol: fifthClassSymbol)
    let elevationBreaks = [firstClassBreak, secondClassBreak, thirdClassBreak, fourthClassBreak, fifthClassBreak]
    // Creates and assigns a class breaks renderer to the feature layer.
    let elevationClassBreaksRenderer = ClassBreaksRenderer(fieldName: "ELEV_GAIN", classBreaks: elevationBreaks)
    featureLayer.renderer = elevationClassBreaksRenderer
    // Sets the layer opacity to semi-transparent.
    featureLayer.opacity = 0.75
    // Adds the feature layer to the map.
    map.addOperationalLayer(featureLayer)
    }
  2. Update the MapView task to call the new addTrailsLayer() method.

    ContentView.swift
    // Displays the map.
    MapView(map: map)
    .task {
    makeOpenSpaceLayer()
    addTrailsLayer()
    }
  3. Press Command + R to run the app.

When the app opens, the Trails feature layer is added to the map. The map displays trails with different symbols depending on trail elevation.

Add layers with definition expressions

You can use a definition expression to define a subset of features to display. Features that do not meet the expression criteria are not displayed by the layer. In the following steps, you will create two methods that use a definition expression to apply a symbol to a subset of features in the Trails feature layer.

  1. Add a method with a definition expression to filter for trails that permit bikes.

    ContentView.swift
    private func addBikeOnlyTrailsLayer() {
    // Creates a trails feature layer.
    let featureLayer = makeFeatureLayer(url: .bikesTrails)
    // Writes a definition expression to filter for trails that do permit the use of bikes.
    featureLayer.definitionExpression = "USE_BIKE = 'Yes'"
    // Creates and assigns a simple renderer to the feature layer.
    let bikeTrailSymbol = SimpleLineSymbol(style: .dot, color: .blue, width: 2.0)
    let bikeTrailRenderer = SimpleRenderer(symbol: bikeTrailSymbol)
    featureLayer.renderer = bikeTrailRenderer
    // Adds the feature layer to the map.
    map.addOperationalLayer(featureLayer)
    }
  2. Add another method with a definition expression to filter for trails that don’t allow bikes.

    ContentView.swift
    private func addNoBikeTrailsLayer() {
    // Creates a no bike trails feature layer.
    let featureLayer = makeFeatureLayer(url: .bikesTrails)
    // Writes a definition expression to filter for trails that don't permit the use of bikes.
    featureLayer.definitionExpression = "USE_BIKE = 'No'"
    // Creates and assigns a simple renderer to the feature layer.
    let noBikeTrailSymbol = SimpleLineSymbol(style: .dot, color: .red, width: 2.0)
    let noBikeTrailRenderer = SimpleRenderer(symbol: noBikeTrailSymbol)
    featureLayer.renderer = noBikeTrailRenderer
    // Adds the feature layer to the map.
    map.addOperationalLayer(featureLayer)
    }
  3. Update the MapView task to call the new addBikeOnlyTrailsLayer() and addNoBikeTrailsLayer() methods.

    ContentView.swift
    // Displays the map.
    MapView(map: map)
    .task {
    makeOpenSpaceLayer()
    addTrailsLayer()
    addNoBikeTrailsLayer()
    addBikeOnlyTrailsLayer()
    }
  4. Press Command + R to run the app.

When the app opens, two Trails feature layers are added to the map. One shows where bikes are permitted and the other where they are prohibited.

Add a layer with a label definition

Create a method to style trailheads with hiker images and labels for the Trailheads feature layer.

  1. Create a helper method named makeLabelDefinition() to define a label definition based on a specific attribute of the feature layer TRL_NAME. Also define label placement and symbol.

    ContentView.swift
    private func makeLabelDefinition() -> LabelDefinition {
    let trailHeadsTextSymbol = TextSymbol()
    trailHeadsTextSymbol.color = .white
    trailHeadsTextSymbol.size = 20.0
    trailHeadsTextSymbol.haloColor = .red
    trailHeadsTextSymbol.haloWidth = 2.0
    trailHeadsTextSymbol.fontFamily = "Noto Sans"
    trailHeadsTextSymbol.fontStyle = .italic
    trailHeadsTextSymbol.fontWeight = .normal
    // Makes an arcade label expression.
    let expression = "$feature.TRL_NAME"
    let arcadeLabelExpression = ArcadeLabelExpression(arcadeString: expression)
    let labelDefinition = LabelDefinition(labelExpression: arcadeLabelExpression, textSymbol: trailHeadsTextSymbol)
    labelDefinition.placement = .pointAboveCenter
    return labelDefinition
    }
  2. Add a method named addTrailheadsLayer().

    Use a PictureMarkerSymbol to draw a trailhead hiker image. Use the LabelDefinition to label each trailhead by its name.

    ContentView.swift
    private func addTrailheadsLayer() {
    // Creates a trailheads feature layer.
    let featureLayer = makeFeatureLayer(url: .trailheads)
    let pictureMarkerSymbol = PictureMarkerSymbol(url: .trailheadImage)
    pictureMarkerSymbol.height = 18.0
    pictureMarkerSymbol.width = 18.0
    let simpleRenderer = SimpleRenderer(symbol: pictureMarkerSymbol)
    featureLayer.renderer = simpleRenderer
    featureLayer.labelsAreEnabled = true
    let trailHeadsDefinition = makeLabelDefinition()
    featureLayer.addLabelDefinition(trailHeadsDefinition)
    // Adds the feature layer to the map.
    map.addOperationalLayer(featureLayer)
    }
  3. Update the MapView task to call the new addTrailheadsLayer() method.

    ContentView.swift
    // Displays the map.
    MapView(map: map)
    .task {
    makeOpenSpaceLayer()
    addTrailsLayer()
    addNoBikeTrailsLayer()
    addBikeOnlyTrailsLayer()
    addTrailheadsLayer()
    }

Run the solution

Press Command + R to run the app.

When the app opens, all the layers you’ve created and symbolized are displayed on the map.

  • Parks and open spaces are displayed with four unique symbols
  • Trails use different symbols (line widths) depending on trail elevation
  • Trails are blue where bikes are permitted and red where they are prohibited
  • Trailheads are displayed with a hiker icon and labels display each trail’s name

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 first set up authentication to create credentials, and then add the developer credentials to the solution.

Set up authentication

To access the secure ArcGIS location services ArcGIS Location Services, also referred to as Location Services, are services hosted by Esri that provide geospatial functionality for developing mapping applications. They include the ArcGIS Basemap Styles service, ArcGIS Static Basemap Tiles service, ArcGIS Places service, ArcGIS Geocoding service, ArcGIS Routing service, ArcGIS GeoEnrichment service, and ArcGIS Elevation service. An ArcGIS Location Platform or ArcGIS Online account is required to use the services. Learn more used in this tutorial, you must implement API key authentication API key authentication is a type of authentication that uses an API key to authenticate requests to ArcGIS services and secure portal items. Learn more or user authentication User authentication is a type of authentication that allows users with an ArcGIS account to sign into an application and allow it to access ArcGIS content, services, and resources on their behalf. The typical authorization protocol used is OAuth2.0. Learn more using an ArcGIS Location Platform An ArcGIS Location Platform account, formerly known as an ArcGIS Developer account, is an identity associated with an ArcGIS Location Platform subscription. Learn more or an ArcGIS Online An ArcGIS Online account, also known as an ArcGIS Organization account, is an identity associated with an ArcGIS Online subscription. It can be used to access ArcGIS tools and develop applications with ArcGIS location services for an organization. Learn more account.

To complete this tutorial, click on the tab in the switcher below for your authentication type of choice, either API key authentication or User authentication.

Create a new API key access token An access token is an authorization string that provides access to secure ArcGIS content, data, and services. Its capabilities are determined by the privileges it supports. It is obtained by implementing API key authentication, User authentication, or App authentication. Learn more with privileges Privileges are a set of permissions assigned to ArcGIS accounts, developer credentials, and applications that grant access to secure resources and functionality in ArcGIS. Learn more to access the secure resources used in this tutorial.

  1. Complete the Create an API key tutorial and create an API key with the following privilege(s) Privileges are a set of permissions assigned to ArcGIS accounts, developer credentials, and applications that grant access to secure resources and functionality in ArcGIS. Learn more :

    • Privileges
      • Location services > Basemaps
  2. Copy and paste the API key access token into a safe location. It will be used in a later step.

Set developer credentials in the solution

To allow your app users to access ArcGIS location services ArcGIS Location Services, also referred to as Location Services, are services hosted by Esri that provide geospatial functionality for developing mapping applications. They include the ArcGIS Basemap Styles service, ArcGIS Static Basemap Tiles service, ArcGIS Places service, ArcGIS Geocoding service, ArcGIS Routing service, ArcGIS GeoEnrichment service, and ArcGIS Elevation service. An ArcGIS Location Platform or ArcGIS Online account is required to use the services. Learn more , use the developer credentials that you created in the Set up authentication step to authenticate requests for resources.

Pass your API Key access token to the ArcGISEnvironment.

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

  2. Set the AuthenticationMode to .apiKey.

    MainApp.swift
    // Change the `AuthenticationMode` to `.apiKey` if your application uses API key authentication.
    private var authenticationMode: AuthenticationMode { .apiKey }
  3. Set the apiKey property with your API key access token.

    MainApp.swift
    31 collapsed lines
    // Copyright 2022 Esri
    //
    // Licensed under the Apache License, Version 2.0 (the "License");
    // you may not use this file except in compliance with the License.
    // You may obtain a copy of the License at
    //
    // https://www.apache.org/licenses/LICENSE-2.0
    //
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.
    import SwiftUI
    import ArcGIS
    import ArcGISToolkit
    @main
    struct MainApp: App {
    // The authentication mode.
    private enum AuthenticationMode {
    case apiKey
    case user
    }
    // Change the `AuthenticationMode` to `.apiKey` if your application uses API key authentication.
    private var authenticationMode: AuthenticationMode { .apiKey }
    // Please enter an API key access token if your application uses API key authentication.
    private let apiKey = APIKey("<#YOUR-ACCESS-TOKEN#>")
    43 collapsed lines
    // Setup an `Authenticator` with OAuth configuration if your application uses OAuth credentials.
    @ObservedObject var authenticator = Authenticator(
    oAuthUserConfigurations: [
    OAuthUserConfiguration(
    // Please enter OAuth credentials for user authentication.
    portalURL: URL(string: "<#YOUR-PORTAL-URL#>")!,
    clientID: "<#YOUR-CLIENT-ID#>",
    redirectURL: URL(string: "<#YOUR-REDIRECT-URL#>")!
    )
    ]
    )
    func setAuthentication() {
    switch authenticationMode {
    case .apiKey:
    ArcGISEnvironment.apiKey = apiKey
    case .user:
    ArcGISEnvironment.authenticationManager.arcGISAuthenticationChallengeHandler = authenticator
    }
    }
    init() {
    setAuthentication()
    }
    var body: some SwiftUI.Scene {
    WindowGroup {
    ContentView()
    .authenticator(authenticator)
    .ignoresSafeArea()
    }
    }
    }

Best Practice: The access token is stored directly in the code as a convenience for this tutorial. Do not store credentials directly in source code in a production environment.

Run the solution

Press Command + R to run the app.

When the app opens, all the layers you’ve created and symbolized are displayed on the map.

  • Parks and open spaces are displayed with four unique symbols
  • Trails use different symbols (line widths) depending on trail elevation
  • Trails are blue where bikes are permitted and red where they are prohibited
  • Trailheads are displayed with a hiker icon and labels display each trail’s name

What’s next?

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