Creating a map options view

Creating a map options view

The built-in AWFMapOptionsViewController provides a quick and easy way to control the map layers and various options for an AWFWeatherMap instance. However, you may want to provide a custom map options view within your own applications instead of the built-in version.

The basic approach is to use an UITableView to display the available options, which can then be divided into sections as needed based on any particular grouping of options. This is what the built-in AWFMapOptionsViewController automatically does for you.

The following is a basic implementation of setting up a custom map options view using a UITableView, which can then be customized further using custom UITableViewCell instances as required by your application. Since the example below posts a notification when weather layers are ready to be added and/or removed based on the option selections, you'll need to observe this notification where appropriate so you can then add and remove the layers on your weather map instance.

import UIKit
import AerisMapKit
class MapOptionsViewController: UIViewController {
    static let LayersDidChange = NSNotification.Name("MapLayersDidChange")
    let tableView = UITableView()
    // array to store the supported layer options to display in the table view
    var layerOptions = [AWFMapLayer]()
    // currently active layers on the map, set before this controller is presented
    var activeLayers = [AWFMapLayer]()
    // keep track of layer selection/deselection so we know what needs to be added/removed
    // when this controller is dismissed
    var layersToAdd = [AWFMapLayer]()
    var layersToRemove = [AWFMapLayer]()
    override func viewDidLoad() {
        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.dataSource = self
        tableView.delegate = self
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "LayerCell")
        NSLayoutConstraint.activate([tableView.topAnchor.constraint(equalTo: view.topAnchor),
                                     tableView.leftAnchor.constraint(equalTo: view.leftAnchor),
                                     tableView.rightAnchor.constraint(equalTo: view.rightAnchor),
                                     tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)])
        // array of layer options to display in the table view
        layerOptions = [.radar, .advisories]
    override func viewWillDisappear(_ animated: Bool) {
        NotificationCenter.default.post(name: MapOptionsViewController.LayersDidChange, object: self, userInfo: ["add": layersToAdd, "remove": layersToRemove])
    fileprivate func isLayerActive(layer: AWFMapLayer) -> Bool {
        return (activeLayers.contains(layer) && layersToRemove.contains(layer) == false) || layersToAdd.contains(layer)
extension MapOptionsViewController: UITableViewDataSource {
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return layerOptions.count
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "LayerCell", for: indexPath)
        let layer = layerOptions[indexPath.row]
        let selected = isLayerActive(layer: layer)
        cell.textLabel?.text = AWFWeatherLayer.name(forLayerType: layer)
        if selected {
            tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
        } else {
            tableView.deselectRow(at: indexPath, animated: false)
        return cell
extension MapOptionsViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let layer = layerOptions[indexPath.row]
        if !layersToAdd.contains(layer) {
    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
        let layer = layerOptions[indexPath.row]
        if let index = layersToRemove.index(of: layer) {
            layersToRemove.remove(at: index)