Feature layer

An ArcGIS feature layer can display features from an ArcGIS Server feature service or a layer of an ArcGIS Server map service. You can perform queries and selections on features, and work with feature attachments. When using an editable ArcGIS Server feature service, you can also edit features and their attachments. The feature layer honors defintion 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 datasets that contain features that need to be displayed in the map, for example, real-world entities such as buildings, pipes, and parcels. 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, then draws them onto the map. This is different from a dynamic layer or a tiled layer that relies on the service to render features into images, which are then displayed on the map. When 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 additional 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. 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 display, whereas the feature layer automatically retrieves them from the service layer. You should never directly add or remove any graphics from the feature layer like you do with the graphics layer.

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

To instantiate a feature layer, provide a URL to a layer in a map service or feature service REST endpoint. This URL is usually formatted as http://<server:port>/<instance>/rest/services/<service>/MapServer/<layerid> or http://<server:port>/<instance>/rest/services/<service>/FeatureServer/<layerid>.

Also, specify a mode while creating the feature layer. The mode decides how the layer retrieves features from the service layer.

Snapshot mode

In snapshot mode, all features belonging to the service layer are retrieved when the feature layer loads. This mode is useful only if the number of features is reasonably small. Perhaps 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 could 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 loads. As the user navigates the map, the layer fetches more features for subsequent map extents. At any time, only those features that need to display 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 within an extent twice as large as the current extent. This could 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 fetch features again 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. The autoRefreshOnExpiration 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 could potentially require more network requests than snapshot mode because features may be fetched every time you navigate the map. It also has the potential to use less memory than snapshot mode as long as the map extents require only a subset of features to fetch from the service layer.

Selection mode

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

Selecting features

When the feature layer operates in selection mode, you can perform selection operations that retrieve features from the service and display them on the map. The features display 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.

let cyanSquare = AGSSimpleMarkerSymbol(color: UIColor.cyanColor())
cyanSquare.style = .Square
cyanSquare.size = 18
featureLayer.selectionSymbol = cyanSquare

Perform selections using selectFeaturesWithQuery:selectionMethod: by providing a selection query and a selection method. The selection query can be based on attribute relationships, or 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.

let query = AGSQuery()
query.whereClause = "POPULATION > 100000"
query.spatialRelationship = .Within
query.geometry = californiaGeometry
featureLayer.selectFeaturesWithQuery(query, selectionMethod: .Add)

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 described above.

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

Querying features

As discussed previously, the feature layer automatically retrieves features that need to display on the map. 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 even 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. Set one of your classes as the queryDelegate to receive this information.

Editing features

XWhen the feature layer displays features, with an editable ArcGIS feature service, you can make changes to those features, delete them, or add new features to the service. It is possible that the server administrator may have disabled the editing capability of the feature service so 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 if a layer is editable by inspecting the editable property as follows:

if !featureLayer.editable {
 println("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 clicking the map, or by iterating through the graphics collection of the layer. If you know the ObjectID of the feature you're looking for, you can find its corresponding graphic by using the convenience lookupFeatureWithObjectId: method.

Once you have a reference to the graphic, you can make changes to its geometry or attributes. These changes are only applied on the computer and the service remains unmodified. Call updateFeatures: when you are ready to post your changes to the service.

//modify the graphic
let graphic = AGSGraphic()
if featureLayer.canUpdateFeature(graphic) {
 graphic.geometry = newGeometry
 graphic.setAttribute(value: "<new-value>", forKey: "<field-name>")
 //update the service 

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

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

featureLayer.deleteFeaturesWithWhereClause("<field-name> = <value>", geometry: nil, spatialRelation: .Contains)

To add a new feature, construct a graphic for it. To construct a graphic, specify a feature type or feature template.

Features in a layer can be of many types. For example, schools can be of type public or private. Each type may display with a different symbol on the map. To create a new school feature, specify its type (if 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 or 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.

let privateSchool = featureLayer.types[index] as AGSFeatureType
let newSchool = featureLayer.featureWithType(privateSchool)

Even when you have constructed the graphic, note that it is still not added to the layer and won't display on the map. Call addFeatures: if you are ready to add the feature to the service. When this operation succeeds, the graphic is automatically added to the feature layer and displays on the map.


If you do not want to immediately persist the graphic to the feature service, manually add it to the feature layer's graphics collection by using addGraphic:. If the graphic has a valid geometry, it is displayed by the map. You can later call addFeatures: to persist the graphic to the service. If you decide not to persist the graphic, 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 are performing a large number of edits, it is expensive to perform them as separate operations. When possible, it is 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 may 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 on the Services Directory page for the feature service layer.

Feature service layer attachments property

You can also programmatically check if the layer supports attachments by inspecting the attachments property as follows:

if !featureLayer.attachments {
 println("Layer does not support attachments")
 //bail out

To get attachments for a particular feature, determine if that feature has any attachments. 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
let oid:UInt = 1

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

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

func featureLayer(featureLayer: AGSFeatureLayer!, operation op: NSOperation!, didQueryAttachmentInfosWithResults attachmentInfos: [AnyObject]!) {
 println("Attachment Count : \(attachmentInfos.count)")
 for attInfo in attachmentInfos as [AGSAttachmentInfo] {
  println("Attachment ID : \(attInfo.attachmentId)")

Once you know that the feature has attachments, 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:.

The AGSAttachmentManager greatly simplifies working with attachments by providing a high-level, coarse grained API on top of the functionality provided by the feature layer.