Access feature data in the cloud

This topic describes how to build an iOS application to consume feature data from the cloud. It's assumed that you've already added a map to your application as described in Adding 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 layer depends on ArcGIS feature services, which provide access to the data, accept and persist edits, and allow the layer to filter data using SQL-like queries. The feature services can be hosted on ArcGIS Online (Esri's cloud) or on your on-premise servers. In this topic, you'll be using a feature service on ArcGIS Online.

Learn more about feature layers

1. Add data from a feature service

Adding data from a feature service is as simple as instantiating a feature layer and adding it to your map. To instantiate the layer, all you need is a URL to the feature service you're going to use, and optionally, the user credentials to access that service. The service you're using in this topic is public, so you do not need to provide any credentials. After adding the layer to the map, you'll customize the symbology of the layer to display its data as blue dots on the map.

- (void)viewDidLoad 
    [super viewDidLoad];
    //code from previous tutorial to add a basemap tiled layer
    NSURL* url = [NSURL URLWithString:@""];
    AGSTiledMapServiceLayer *tiledLayer = [AGSTiledMapServiceLayer tiledMapServiceLayerWithURL:url];
    [self.mapView addMapLayer:tiledLayer withName:@"Basemap Tiled Layer"];

    NSURL *featureLayerURL = [NSURL URLWithString:@""];
    AGSFeatureLayer *featureLayer = [AGSFeatureLayer featureServiceLayerWithURL:featureLayerURL mode:AGSFeatureLayerModeOnDemand];
    [self.mapView addMapLayer:featureLayer withName:@"CloudData"];

    AGSSimpleMarkerSymbol *featureSymbol = [AGSSimpleMarkerSymbol simpleMarkerSymbolWithColor:[UIColor colorWithRed:0 green:0.46 blue:0.68 alpha:1]];
    featureSymbol.size = CGSizeMake(7,7); = AGSSimpleMarkerSymbolStyleCircle;
    featureSymbol.outline = nil;
    featureLayer.renderer = [AGSSimpleRenderer simpleRendererWithSymbol:featureSymbol];

2. Allow a user to select features

In this section, you'll allow a user to select a country from a list. To do this, you'll add a button to the UI and connect the button's Touch Up Inside event to an action method on the view controller called showCountryPicker:.

Wiring up action methods in interface builder

When a user taps the button, the view controller's method showCountryPicker: will be invoked. In this method, you'll instantiate UIPickerView and display it on screen. To add a list of countries to the picker, you'll set the view controller as the picker's data source and implement the methods defined in the UIPickerViewDataSource protocol. Finally, you'll also set the view controller as the picker's delegate and implement the pickerView:didSelectRow:inComponent: method defined in the UIPickerViewDelegate protocol to allow the picker to inform you when a user selects a country.

- (IBAction)showCountryPicker:(id)sender
       self.countries = @[@"None",@"US",@"Canada",@"France",@"Australia",@"Brazil"];   
        self.countryPicker = [[UIPickerView alloc]init];
        self.countryPicker.delegate = self;
        self.countryPicker.dataSource = self;
        self.countryPicker.showsSelectionIndicator  = YES;
        self.countryPicker.backgroundColor = [UIColor whiteColor];    
        [self.view addSubview:self.countryPicker];
        self.countryPicker.translatesAutoresizingMaskIntoConstraints = NO;
        //add auto-layout constraints to properly position the picker
        NSMutableDictionary* views = [[NSMutableDictionary alloc]init];
        [views setObject:self.countryPicker forKey:@"countryPicker"];
        [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[countryPicker]|" options:nil metrics:nil views:views]];
        [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[countryPicker]|" options:nil metrics:nil views:views]];
    self.countryPicker.hidden = NO;

-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
    return 1;

-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
    return self.countries.count;

-(NSString *)pickerView:(UIPickerView *)pickerView
    return self.countries[row];

3. Display selected features

In this section, you'll highlight the features that belong to the country selected by the user.

First, you'll get the country selected by the user. If the user selected None, clear any selection on the feature layer. Otherwise, select features using the SQL-like statement COUNTRY = <selected_country>. Before you perform the selection, you need to set the selection symbol so that selected features are symbolized with red dots on the map. You also need to set the view controller as the feature layer's queryDelegate. This will allow the view controller to respond when the selection is complete. As part of being the query delegate, the view controller needs to adopt the AGSFeatureLayerQueryDelegate protocol and implement the methods defined in that protocol that are relevant.

-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
    NSString* countryName = self.countries[row];

    AGSFeatureLayer *featureLayer = (AGSFeatureLayer *)[self.mapView mapLayerForName:@"CloudData"];
        AGSSimpleMarkerSymbol *selectedFeatureSymbol = [AGSSimpleMarkerSymbol simpleMarkerSymbol]; = AGSSimpleMarkerSymbolStyleCircle;
        selectedFeatureSymbol.color = [UIColor colorWithRed:0.78 green:0.3 blue:0.19 alpha:1];
        selectedFeatureSymbol.size = CGSizeMake(10,10);
        featureLayer.selectionSymbol = selectedFeatureSymbol;

       featureLayer.queryDelegate = self;

    if ([countryName isEqualToString:@"None"])
        [featureLayer clearSelection];
        AGSQuery *selectQuery = [AGSQuery query];
        selectQuery.whereClause = [NSString stringWithFormat:@"CNTRY_NAME = '%@'", countryName];
        [featureLayer selectFeaturesWithQuery:selectQuery selectionMethod:AGSFeatureLayerSelectionMethodNew];

    self.countryPicker.hidden = YES;

When the selection operation is complete, the view controller's featureLayer:operation:didSelectFeaturesWithFeatureSet: method will be invoked. In this method, you'll iterate through the selected features and create a minimum bounding envelope that covers all these features. You'll then zoom the map to this envelope.

-(void)featureLayer:(AGSFeatureLayer *)featureLayer operation:(NSOperation *)op didSelectFeaturesWithFeatureSet:(AGSFeatureSet *)featureSet

    AGSMutableEnvelope *env = nil;
    for (AGSGraphic *selectedFeature in featureSet.features)
        if (env)
            [env unionWithEnvelope:selectedFeature.geometry.envelope];
            env = [selectedFeature.geometry.envelope mutableCopy];
    [self.mapView zoomToGeometry:env withPadding:20 animated:YES];

4. 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. Now you need to declare the properties you've been using as well as the delegate protocols you've adopted. You do this in the view controller's header file.

@interface ViewController : UIViewController < AGSMapViewLayerDelegate, AGSFeatureLayerQueryDelegate , UIPickerViewDelegate, UIPickerViewDataSource> {

@property (nonatomic, strong) IBOutlet AGSMapView *mapView;
@property (nonatomic, strong) NSArray *countries;
@property (nonatomic,strong) UIPickerView* countryPicker;
- (IBAction)showCountryPicker:(id)sender ;