Show legend

View on GitHub
Sample viewer app

Show a legend for all the operational layers in the map.

Image of Show legend 1 Image of Show legend 2 Image of Show legend 3

Use case

Legends are used to describe what each symbol on a map represents. A common format is to show an image of the symbol alongside of a text description of what that symbol represents. This sample demonstrates how to show a legend for all the operational layers in the map.

How to use the sample

  1. Open the sample
  2. Scroll through the legends to see the various elements that represent features on the map.

How it works

  1. Layers implement the AGSLayerContent interface, which provides an API for getting AGSLegendInfo objects. AGSLegendInfo contains an AGSSymbol and a name string. AGSLayerContent.fetchLegendInfos(completion:) must be called on each AGSLayerContent instance to fetch the info from the data.
  2. For each symbol in the AGSLegendInfo array, AGSSymbol.createSwatch(completion:) must be called so that an image of the AGSSymbol is returned.
  3. The names and images are then displayed next to each other in a list.

Relevant API

  • AGSLayerContent
  • AGSLegendInfo

Tags

legend, legend info, symbol swatch, toolkit

Sample Code

MILLegendTableViewController.swiftMILShowLegendViewController.swift
                                                                                                              
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
// Copyright 2016 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
//
//   http://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 UIKit
import ArcGIS

class MILLegendTableViewController: UITableViewController {
    var operationalLayers: NSMutableArray!
    var legendInfosDict = [String: [AGSLegendInfo]]()
    private var orderArray = [AGSLayerContent]()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.populateLegends(with: self.operationalLayers as! [AGSLayerContent])
    }

    func populateLegends(with layers: [AGSLayerContent]) {
        for layer in layers {
            if !layer.subLayerContents.isEmpty {
                self.populateLegends(with: layer.subLayerContents)
            } else {
                // else if no sublayers fetch legend info
                self.orderArray.append(layer)
                layer.fetchLegendInfos { [weak self] (legendInfos, error) in
                    if let error = error {
                        print(error)
                    } else {
                        if let legendInfos = legendInfos {
                            self?.legendInfosDict[self!.hashString(for: layer)] = legendInfos
                            self?.tableView.reloadData()
                        }
                    }
                }
            }
        }
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        // Return the number of sections.
        return orderArray.count
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // Return the number of rows in the section.
        let layer = self.orderArray[section]
        let legendInfos = self.legendInfosDict[self.hashString(for: layer)]
        return legendInfos?.count ?? 0
    }

    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        let layerContent = self.orderArray[section]
        return self.nameForLayerContent(layerContent)
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "MILLegendCell", for: indexPath)

        let layer = self.orderArray[indexPath.section]
        let legendInfos = self.legendInfosDict[self.hashString(for: layer)]!
        let legendInfo = legendInfos[indexPath.row]

        cell.textLabel?.text = legendInfo.name
        legendInfo.symbol?.createSwatch { (image, _) in
            if let updateCell = tableView.cellForRow(at: indexPath) {
                updateCell.imageView?.image = image
                updateCell.setNeedsLayout()
            }
        }

        return cell
    }

    func geometryTypeForSymbol(_ symbol: AGSSymbol) -> AGSGeometryType {
        if symbol is AGSFillSymbol {
            return AGSGeometryType.polygon
        } else if symbol is AGSLineSymbol {
            return .polyline
        } else {
            return .point
        }
    }

    // MARK: - Helper functions

    func hashString (for obj: AnyObject) -> String {
        return String(UInt(bitPattern: ObjectIdentifier(obj)))
    }

    func nameForLayerContent(_ layerContent: AGSLayerContent) -> String {
        if let layer = layerContent as? AGSLayer {
            return layer.name
        } else {
            return (layerContent as! AGSArcGISSublayer).name
        }
    }
}

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