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.

//implementation file
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
 //Get the feature service data from the cloud
 NSURL *featureLayerURL = [NSURL URLWithString:@""];
 AGSFeatureLayer *featureLayer = [AGSFeatureLayer featureServiceLayerWithURL:featureLayerURL mode:AGSFeatureLayerModeOnDemand];
 featureLayer.outFields = @[@"*"];
 featureLayer.calloutDelegate = self;
 // Set the Featurelayer symbology
 AGSSimpleMarkerSymbol *featureSymbol = [AGSSimpleMarkerSymbol simpleMarkerSymbolWithColor:[NSColor colorWithRed:0 green:0.46 blue:0.68 alpha:1]];
 featureSymbol.size = CGSizeMake(7,7); = AGSSimpleMarkerSymbolStyleCircle;
 featureSymbol.outline = nil;
 featureLayer.renderer = [AGSSimpleRenderer simpleRendererWithSymbol:featureSymbol];
 //Add the feature service
 [self.mapView addMapLayer:featureLayer withName:@"World Cities"];

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 header file (AppDelegate.h) displays alongside the Canvas. Locate the table view in the Dock, then drag and drop it in the header 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.

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.

//header file
#import <Cocoa/Cocoa.h>
#import <ArcGIS/ArcGIS.h>

@interface AppDelegate : NSObject <NSApplicationDelegate, 
 NSTableViewDataSource, NSTableViewDelegate>

@property (assign) IBOutlet NSWindow *window;
@property (strong) IBOutlet AGSMapView *mapView;
@property (strong) IBOutlet NSTableView *tableView;
@property (strong) NSArray *countries;


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.

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
 //Set the table view's delegate and datasource
 self.tableView.dataSource = self;
 self.tableView.delegate = self;

 //Create an array of country names
 self.countries = @[@"World",@"Australia",@"Brazil",@"Canada",@"Denmark",@"Egypt",@"France",@"Germany",@"Hungary",@"India",@"Italy",@"Japan",@"Kazakhstan",@"Libya",@"Mexico",@"Nigeria",@"Oman",@"Pakistan",@"Qatar",@"Russia",@"South Africa",@"Thailand",@"US",@"Vietnam",@"Yemen",@"Zambia"];

 //Load the Country Names into the table view. Using the viewForTableColumn delegate method
 [self.tableView reloadData];


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
- (void)tableViewSelectionDidChange: (NSNotification *)aNotification {
 if ([self.tableView selectedRow] >= 0) {
  //Get the Country Name from the selected row
  NSString* countryName = [self.countries objectAtIndex:[self.tableView selectedRow]];
  //Get the feature layer
  AGSFeatureLayer *featureLayer = (AGSFeatureLayer *)[self.mapView mapLayerForName:@"World Cities"];
  //Create and set a red selection symbol
   //Set the symbolology for selected features in the featurelayer (selectionSymbol)
   AGSSimpleMarkerSymbol *selectedFeatureSymbol = [AGSSimpleMarkerSymbol simpleMarkerSymbol]; = AGSSimpleMarkerSymbolStyleCircle;
   selectedFeatureSymbol.color = [NSColor colorWithRed: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
  AGSQuery *selectQuery = [AGSQuery query];
  selectQuery.outFields = [NSArray arrayWithObjects:@"*", nil];
  selectQuery.where = [NSString stringWithFormat:@"COUNTRY = '%@'", countryName];
  //Set the feature layer's query delegate to be the application       
  featureLayer.queryDelegate = self;
  //Select features based on the query
  [featureLayer selectFeaturesWithQuery:selectQuery selectionMethod:AGSFeatureLayerSelectionMethodNew];

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.

//Step through the selected features returned in the featureSet
-(void)featureLayer:(AGSFeatureLayer *)featureLayer operation:(NSOperation *)op didSelectFeaturesWithFeatureSet:(AGSFeatureSet *)featureSet
    //Zoom to the extent of the unioned cities
    AGSMutableEnvelope *env = nil;
    for (AGSGraphic *selectedFeature in featureSet.features){
        if (env)
            [env unionWithEnvelope:selectedFeature.geometry.envelope];
            env = [selectedFeature.geometry.envelope mutableCopy];
    [self.mapView zoomToScale:50000000 animated:YES];

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.