Skip To Content

ArcGIS Feature layer

In this topic

An ArcGIS Feature layer displays features from a layer of an ArcGIS Server Feature Service or an ArcGIS Server Map Service. You can perform queries and selections on features and work with feature attachments. When using an ArcGIS Server Feature Service, you can also edit features and their attachments. The feature layer honors definition queries, scale dependencies, and other properties configured on the service layer.

Feature Services, like Map Services, are based on map documents (*.mxd and *.msd files). A map document contains references to GIS datasets. These datasets contain the features that need to be displayed in the map. Features are real world entities such as buildings, pipes, and parcels. Features are organized into layers in a map document. For example, the map document of a national park may contain separate layers for hiking trails, picnic areas, and campgrounds. Map documents can be published to ArcGIS Server to create Map and Feature services.

ArcGIS Server Map and Feature services are accessible on the web as SOAP and REST web services. You can find the URL of these web services using the ArcGIS Server Services Directory.

The feature layer retrieves features from the service layer, holds them in memory on the device, then draws them onto the map using the device's graphics capabilities. This is different from a dynamic layer or a tiled layer, which rely on the service to render features into images that are then displayed on the map. Whenever you navigate the map, dynamic and tiled layers fetch new map images to display, but the feature layer may already have all the features it needs to display, or it may fetch some more features. In some cases, a feature layer can be more efficient than a dynamic or tiled layer because it does not have to make frequent round trips to the server.

Displaying features

The feature layer inherits its drawing capabilities from the graphics layer. Thus, in a way, they both provide the same functionality for displaying features. However, one key difference is that the graphics layer requires you to provide the graphics that need to be displayed, whereas the feature layer automatically retrieves the features from the service layer. Consequently, you should never directly add or remove any graphics from the feature layer as you do with the graphics layer.

Another difference is that the graphics layer requires you to provide either a renderer or the symbols needed for displaying the graphics, whereas the feature layer inherits its symbology from the service layer when the service is hosted on ArcGIS Server 10 or later. If the service is from an earlier server, you need to assign a renderer for the feature layer to symbolize the features.

To instantiate a feature layer, you need to provide a URL to a layer in a Map Service or Feature Service REST endpoint. This URL is usually of the form http://<server:port>/<instance>/rest/services/<service>/MapServer/<layerid> or http://<server:port>/<instance>/rest/services/<service>/FeatureServer/<layerid>.

You also need to specify a mode while creating the feature layer. The mode determines how the layer will retrieve features from the service layer.

NSURL* url = [NSURL URLWithString: @"http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StateCityHighway_USA/MapServer/0"]; 	 
AGSFeatureLayer* featureLayer = [AGSFeatureLayer featureServiceLayerWithURL: url mode: AGSFeatureLayerModeOnDemand];

Snapshot mode

In snapshot mode, all features belonging to the service layer are retrieved when the feature layer is loaded. This mode is useful only if the number of features is reasonably small. iOS applications are constrained by the amount of memory available to them on a device, and it is not practical to hold large numbers of features in memory. The number of features actually retrieved depends on the limits set on the service. By default, ArcGIS Server 10 services only allow 1000 features to be retrieved, but this can be configured differently by the server administrator. Once the features are retrieved, the layer does not request more features from the service.

On-demand mode

In on-demand mode, only features within the map's extent are retrieved from the service layer when the feature layer is loaded. As the user navigates the map, the layer fetches more features for subsequent map extents. Thus, at any time, only those features that need to be displayed are retrieved.

You can customize, to a certain degree, how many and how often features are fetched from the service by adjusting the layer's bufferFactor and expirationInterval properties. The buffer factor allows the layer to fetch more features than just those that are within the current map extent. For instance, a buffer factor of 2 allows the layer to fetch features that are within an extent twice as large as the current extent. This can help reduce network requests if subsequent extents fall within the buffered extent. Features will only be fetched when the map's extent goes beyond the buffered extent. The expiration interval forces the layer to re-fetch features that were fetched before the specified interval. This is useful if the data in the service changes frequently and you don't want the layer to display stale features. TheautoRefreshOnExpiration property allows you to specify whether the features should be fetched as soon as the expiration interval elapses, or wait until the user navigates the map.

This mode can potentially require more network requests than snapshot mode because features can be fetched every time you navigate the map. But it also has the potential to use less memory than snapshot mode as long as the map extent requires only a subset of features to be fetched from the service layer.

Selection mode

In selection mode, no features are retrieved when the layer is loaded. Features are retrieved when selection operations are performed. Only those features that are displayed as selected are retrieved from the service. This mode is useful if you want to retrieve specific features and highlight them on the map. You typically use a feature layer in selection mode on top of a dynamic layer using the same service. Features are normally displayed by the dynamic layer and the feature layer is empty. When the user wants to edit some features, a selection operation is performed on the feature layer and the resulting features are displayed as selected. The user edits the selected features, then the selected features are cleared. The feature layer returns to being empty and the updated features are displayed by the dynamic layer.

Selecting features

When the feature layer is operating in selection mode, you can perform selection operations that retrieve features from the service and display them on the map. The features are displayed using the layer's selection symbol. If the selection symbol is not defined, the layer's renderer is used. It is recommended that you specify a selection symbol to make the selected features appear highlighted and stand out from the remaining features.

AGSSimpleMarkerSymbol* cyanSquare = [AGSSimpleMarkerSymbol simpleMarkerSymbolWithColor:[UIColor cyanColor]];
cyanSquare.style = AGSSimpleMarkerSymbolStyleSquare;
cyanSquare.size = CGSizeMake(9,9);
featureLayer.selectionSymbol = cyanSquare;

You perform selections using selectFeaturesWithQuery:selectionMethod: by providing a selection query and a selection method. The selection query can be based on attribute relationships, spatial relationships, or both, for example, selecting all cities that have a population greater than 100,000 and within the state of California. The selection method specifies whether the features satisfying the relationships should be added to the existing set of selected features, removed from the set, or entirely replace the set.

AGSQuery* query = [AGSQuery query]; 
query.whereClause = @"POPULATION > 100000";
query.spatialRelationship = AGSQuerySpatialRelationshipWithin; 
query.geometry = californiaGeometry;  
[featureLayer selectFeaturesWithQuery:query selectionMethod:AGSFeatureLayerSelectionMethodAdd];

The complete set of selected features is accessible through the selectedFeatures property on the layer. Do not add or remove features to the set directly. Instead, use selection operations as previously described.

When you no longer want to display the selected features, you can remove them using clearSelection.

Querying features

As discussed previously, the feature layer automatically retrieves features that need to be displayed on the map. But the layer also provides the ability to retrieve additional features using queries. Queries can be based on attribute relationships, spatial relationships, or both. Queries can return whole features, just the feature identifiers, or related features. The querying capabilities of a feature layer are very similar to that of AGSQueryTask. The pattern of performing queries is also the same. The feature layer informs its queryDelegate when queries complete successfully or encounter errors. You should set one of your classes as the queryDelegate to receive this information.

Editing features

When the feature layer displays features in an ArcGIS Feature Service (as opposed to a Map Service), you can make changes to those features, delete them, or add new features to the service. However, it's possible that the server administrator may have disabled some or all of the editing capabilities of the Feature service. It's always a good idea to make sure that the layer is editable before making any edits. You can determine if a layer is editable by looking for edit operations on the Services Directory page for the Feature Service layer.

Feature Layer Operations

You can also programmatically check what type of edits are permitted by the service by using the methods canCreate, canUpdate, and canDelete methods on AGSFeatureLayer.

if(!featureLayer.editable){
 NSLog(@"Layer does not support editing");
 //bail out
}

To modify an existing feature, you need a reference to the corresponding AGSGraphic object. You can get the graphic in a variety of ways, for example, in response to a user tap on the map, or by iterating through the graphics collection of the layer looking for a graphic with some particular attribute values. If you know the OBJECTID of the feature you're looking for, you can find its corresponding graphic by using the convenience method lookupFeatureWithObjectId:.

Once you have a reference to the graphic, you can make changes to its geometry or attributes. But before doing so, you may want to check if that particular feature can be edited by the current user in case the feature service enforces ownership-based access control on features. To do so, you can use the canUpdateFeature: and canDeleteFeature: methods by passing the feature you want to edit.

Any changes you make to the AGSGraphic object exist only in memory on the device, the service remains unmodified. When you're ready to post your changes to the service, you need to call updateFeatures:.

//modify the graphic  
AGSGraphic* graphic = ... ; 

if([featureLayer canUpdateFeature:graphic]){
    graphic.geometry = newGeometry; 
   [graphic setAttribute:@"<new-value>" forKey:@"<field-name>"];  

    ...

    //update the service 
    [featureLayer updateFeatures:@[graphic]]; 
}

The feature layer informs its editingDelegate when edit operations succeed or encounter errors. You should set one of your classes as the feature layer's editingDelegate to receive results of successful operations and to handle any errors.

To delete features, you can use deleteFeaturesWithObjectIds:, passing in an array of OBJECTIDs of features that need to be deleted. You can also delete features based on attribute or spatial relationships using deleteFeaturesWithWhereClause:geometry:spatialRelation:. In both cases, features are removed from the layer and the service.

[featureLayer deleteFeaturesWithWhereClause:@"<field-name> = <value>" geometry:nil spatialRelation:nil];

To add a new feature, you first need to construct a graphic for it. To construct a graphic, you need to specify a feature type or a feature template.

Features in a layer can be of many types. For example, schools can be of type public or private. Each type can be displayed with a different symbol on the map. To create a new school feature, you need to specify its type; whether it should be a public school or a private school.

A feature template provides default settings for a feature, for example, its attribute values. Templates make it easy to create new features. A layer can have multiple templates. If the layer has feature types, each type can have one or more templates .Feature types and feature templates are defined by the service and are available on the layer through the types and templates properties.

AGSFeatureType* privateSchool = [featureLayer.types objectAtIndex:index];  
AGSGraphic* newSchool = [featureLayer featureWithType:privateSchool];

When you've constructed the graphic, it's still not added to the layer and won't be displayed on the map. If you're ready to add the feature to the service, you need to call addFeatures:. When this operation succeeds, the graphic is automatically added to the feature layer and displayed on the map.

[featureLayer addFeatures:[NSArray arrayWithObject:newSchool]];

If you do not want to immediately persist the graphic to the feature service, you can manually add it to the feature layer's graphics collection by using addGraphic:. If the graphic has a valid geometry, it will be displayed by the map. You can then call addFeatures: to persist the graphic to the service. In the event that you decide not to persist the graphic, you need to manually remove it from the feature layer by using removeGraphic:.

Each add, delete, and update operation is performed over a separate network request. If you're performing a large number of edits, it will be expensive to perform them as separate operations. When possible, it's more efficient to perform all edits in a batch over a single network request using applyEditsWithFeaturesToAdd:toUpdate:toDelete:.

Working with attachments

Features in a layer can have attachments. Attachments can be of various types, such as pictures, documents, videos, and so on. For example, a house may have an image of its blueprint, or a parcel may have a title deed document. Before trying to access or edit attachments, make sure that the layer supports attachments. This information is listed in the Services Directory for the Feature Service layer.

Feature Service Layer attachments property
You can also programmatically check whether the layer supports attachments by inspecting the attachments property as follows:
if(!featureLayer.attachments){
  NSLog(@"Layer does not support attachments");
  //bail out
}

To get attachments for a particular feature, you first need to find out if that feature has any attachments. You do this by calling queryAttachmentInfosForObjectId:, which fetches metadata about the feature's attachments. The metadata includes information such at the content type, name, and a unique identifier for each attachment.

//OBJECTID of a feature
int oid = ...;

[featureLayer queryAttachmentInfosForObjectId: oid];

The feature layer informs its editingDelegate when operations related to attachments succeed or encounter errors. You should set one of your classes as the feature layer's editingDelegate to receive results of successful operations and to handle any errors.

The following code snippet shows the implementation of the delegate method that receives attachment metadata:

- (void) featureLayer:(AGSFeatureLayer *) featureLayer
operation :(NSOperation*) op
didQueryAttachmentInfosWithResults:(NSArray *) attachmentInfos {

	NSLog(@"Attachment Count : %d",[attachmentInfos count]);
	for (AGSAttachmentInfo* attInfo in attachmentInfos) {
         NSLog(@"Attachment ID : %d", attInfo.attachmentId);
		}
}
Once you know that the feature has attachments, you can use retrieveAttachmentForObjectId:attachmentId: to fetch a particular attachment by providing its unique identifier.

If the layer is editable, you can also delete attachments using deleteAttachmentsForObjectId:attachmentIds:, add new attachments using addAttachment:filepath: or addAttachment:data:filename:, or replace existing attachments using updateAttachment:data:filename:attachmentId:.

AGSAttachmentManager simplifies working with attachments by providing a high-level, coarse grained API on top of the functionality provided by the feature layer. See Working with the Attachment Manager for more information.

See also