Access feature data in the cloud

This topic describes how to build an OS X application to consume and query feature data from the cloud. It's assumed that you've already added a map to your application as described in Add a map to your app.

The API provides a feature layer (class name AGSFeatureLayer) that allows you to access and edit vector map data. The API’s feature layer is created out of a Feature or Map service. The service’s meta data provide information such as whether the layer supports edits, queries etc. The service is published on one of the following:

  • ArcGIS Server
  • In the cloud – ArcGIS Online (Esri’s cloud) or your on-premise servers

When data is published on the cloud, the services are said to be hosted. In this topic, you'll be using a feature service on ArcGIS Online

Learn more about feature layers

At the end of this tutorial you will be able to do the following:

  • Add a feature layer from a hosted feature service.
  • Override the default symbology of the layer.
  • Display a list of countries in a table view.
  • Pick a country, select and zoom to its cities.

1. Add data from a feature service

Displaying data from a feature service is simple. You just instantiate the feature layer, using the URL to the feature service, and add it to your map. If the feature service is not public then you will need to provide user credentials to access the service. The service you're using in this topic is public, so you do not need to provide any credentials.

You will override the layer's default symbology to display the cities as blue dots on the map.

func applicationDidFinishLaunching(aNotification: NSNotification?) {

 //Get the feature service data from the cloud
 var featureLayerURL = NSURL(string: "")
 var featureLayer = AGSFeatureLayer.featureServiceLayerWithURL(featureLayerURL, mode: .OnDemand) as AGSFeatureLayer
 featureLayer.outFields = ["*"]
 //Set the FeatureLayer symbology
 var featureSymbol = AGSSimpleMarkerSymbol.simpleMarkerSymbolWithColor(NSColor(red: 0, green: 0.46, blue: 0.68, alpha: 1)) as AGSSimpleMarkerSymbol
 featureSymbol.size = CGSizeMake(7, 7) = .Circle
 featureSymbol.outline = nil
 featureLayer.renderer = AGSSimpleRenderer.simpleRendererWithSymbol(featureSymbol) as AGSSimpleRenderer
 //Add teh feature service
 self.mapView.addMapLayer(featureLayer, withName: "CloudData")

2. Add table view to the UI

In this section, you'll allow a user to select a country from a list displayed in a table view. Select the .xib file in the Project Navigator pane on the left, it’s content is display in the Canvas Section on the right. The rightmost section in Xcode is the Utility area. At the bottom of the Utility area is the Library pane. Select an NSTableView from the Library area and drag and drop it onto the UI.

In order to programmatically access a the table view in .xib file, you need to create a corresponding property (IBOutlet) and connect the two. Xcode simplifies this and can create the property for you. To do this, enable the Assistant Editor so that the swift file (AppDelegate.swift) displays alongside the Canvas. Locate the table view in the Dock, then drag and drop it in the swift file.

Connect NSTableView to Window

Upon doing this, Xcode automatically prompts for a name so that it can create an "outlet" connection from the application delegate to the table view in the UI. In this topic, this outlet is called tableView.

Set the Outlet name

At this point you can build and run the application to see the layout.

Table view UI layout

3. Add a list of Country names to the table view

Firstly, format the table view so that it contains only one column and it's content mode is set to be View Based. In the Attributes Inspector set the Table View's Content Mode and Columns as follows:

Content Mode = View Based

Next, ensure that the table view's data Source and delegate are bound to the App Delegate.

Bind the data Source and delegate

Next, to populate the table view you need to implement the NSTableViewDataSource and the NSTableViewDelegate protocols.

import Cocoa
import ArcGIS

class AppDelegate: NSObject, 
  @IBOutlet weak var window: NSWindow!
  @IBOutlet weak var mapView: AGSMapView!
  @IBOutlet weak var tableView: NSTableView!


Both protocols contain methods that are essential to providing the content and creating the cells for the table view. Specifically, you must implement:

  • numberOfRowsInTableView: tells the table how many rows it needs to display.
  • tableView:viewForTableColumn:row: to create and populate the cell with data.

class AppDelegate: NSObject, NSApplicationDelegate, AGSMapViewLayerDelegate, NSTableViewDataSource, NSTableViewDelegate, AGSFeatureLayerQueryDelegate {
 @IBOutlet weak var tableView: NSTableView!
 @IBOutlet weak var window: NSWindow!
 @IBOutlet weak var mapView: AGSMapView!
 var countries = ["World","Australia","Brazil","Canada","Denmark","Egypt","France",
 "Nigeria","Oman","Pakistan","Qatar","Russia","South Africa","Thailand",


//Provide the number rows required in the table
func numberOfRowsInTableView(tableView: NSTableView!) -> Int {
  return self.countries.count;
//Create and configure the cell that’s displayed in the table view
func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn, row: Int) -> NSView {
 var result = tableView.makeViewWithIdentifier(tableColumn.identifier, owner: self) as NSTableCellView
 result.textField?.stringValue = self.countries[row]
 return result;


4. Display and zoom to all the Cities from the chosen Country

The tableViewSelectionDidChange: delegate method is fired when the user selectes a row (country) in the table. In this method, call the feature layer's selectFeaturesWithQuery: method providing the query object. The selected cities will then be displayed with the red selection symbol.

//Implement the  tableViewSelectionDidChange: method defined in the NSTableViewDelegate protocol
func tableViewSelectionDidChange(notification: NSNotification!) {
 if self.tableView.selectedRow >= 0 {
  //Get the country name from the selected row
  var countryName = self.countries[self.tableView.selectedRow]
  //Get the feature layer
  var featureLayer = self.mapView.mapLayerForName("CloudData") as AGSFeatureLayer
  //create and set a red selection symbol
  if featureLayer.selectionSymbol == nil {
   //Set the symbology for selected features in the featurelayer (selectionSymbol)
   var selectedFeatureSymbol = AGSSimpleMarkerSymbol.simpleMarkerSymbol() as AGSSimpleMarkerSymbol = .Circle
   selectedFeatureSymbol.color = NSColor(red: 0.78, green: 0.3, blue: 0.19, alpha: 1)
   selectedFeatureSymbol.size = CGSizeMake(10, 10)
   featureLayer.selectionSymbol = selectedFeatureSymbol
  //Create a query and specify the where clause
  var selectQuery = AGSQuery.query() as AGSQuery
  var queryString = "COUNTRY = '\(countryName)'"
  selectQuery.whereClause = queryString
  //Set the feature layer's query delegate to the application
  featureLayer.queryDelegate = self
  //Select features based on the query
  featureLayer.selectFeaturesWithQuery(selectQuery, selectionMethod: .New)

To zoom to the extent of the cities contained in the country use the AGSFeatureLayerQueryDelegate protocol method didSelectFeaturesWithFeatureSet: that is fired once the feature set is returned. In this method iterate through the feature set and union all the city points. Zoom the map to the center of the countries cities and display the map at a fixed scale.

func featureLayer(featureLayer: AGSFeatureLayer!, operation op: NSOperation!, didSelectFeaturesWithFeatureSet featureSet: AGSFeatureSet!) {
 //Zoom to the extent of the unioned cities
 var env:AGSMutableEnvelope?
 for selectedFeature in featureSet.features {
  if env != nil {
   env!.unionWithEnvelope((selectedFeature as AGSGraphic).geometry.envelope)
  else {
   env = (selectedFeature as AGSGraphic).geometry.envelope.mutableCopy() as? AGSMutableEnvelope
 self.mapView.zoomToGeometry(env, withPadding: 20, animated: true)

5. Run the application

At this point, you've written all the code required to load data from a feature service and allow a user to highlight features that belong to a country. Build and run your app. It should look like this.

Map with highlighted cities