Identify Task
With the Identify task, you can search the layers in a map for features that intersect an input geometry. Once the matching features are returned, you can display their geometries and attributes in your application. To use an Identify task, you will need to:
- Create the task
- Set the Identify task delegate (in order to receive result)
- Create the parameters which define the task
- Execute the task, usually in response to a user event
- Retreive the results
- Handle any errors
The following sections describe these steps in more detail.
Creating the Identify task
To instantiate an AGSIdentifyTask, you need to provide a URL to a Map service REST web service endpoint. This URL is usually of the form http://<server:port>/<instance>/services/<service>/MapServer. If the web service is secured, you will also need to provide the credentials that can be used to access the service.
NSURL* url = [NSURL URLWithString: @"http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer"];
When you create the task, you need to ensure you take ownership of it. Otherwise, it might get deallocated before it has a chance to execute. If you instantiate the task using alloc, you automatically have ownership. However, if you instantiate an auto-released task using the convenience constructor, you need to take ownership by either sending it a retain message, or by assigning it to a property that will retain it.
//sending a retain message
AGSIdentifyTask* identifyTask = [AGSIdentifyTask identifyTaskWithURL: url];
[identifyTask retain];
//OR assigning to a property that will retain the object
self.task = [AGSIdentifyTask identifyTaskWithURL: url];
When you are finished using the task, you should relinquish ownership so that its memory can be reclaimed. You do this typically in the dealloc method of your view controller by sending the task a release message or by setting the corresponding property to nil
- (void)dealloc {
//sending a release message
[identifyTask release];
//OR setting the property to nil
self.task = nil;
...
}
![Note Note](rsrc/note.png)
Please refer to Apple's Memory Management Programming Guide for more information on how to manage application memory.
identifyTask.delegate = self;
Creating the input parameters for the Identify task
Prior to executing your task you will need to set the Identify parameters. These parameters are stored in a AGSIdentifyParameters object.
AGSIdentifyParameters* identifyParams = [[AGSIdentifyParameters alloc] init];
There are a number properties of the AGSIdentifyParameters object that you need to set. These include the layer ids of the layers in the map service you want to identify, whether to return the geometries of any found features, the spatial reference of the map, etc.. The list of properties and a brief description of each is below:
- Size - The size of the map currently being viewed, in pixels.
- returnGeometry - If "YES", the result set includes the geometry associated with each result. The default is "NO".
- tolerance - the distance in screen pixels from the specified geometry within which the identify should be performed.
- layerOption - Specified which layers to use. This is of type AGSIdentifyParametersLayerOption and can have the following values:
- AGSIdentifyParametersLayerOptionAll (use all layers),
- AGSIdentifyParametersLayerOptionTop (use only the top layer), and
- AGSIdentifyParametersLayerOptionVisible (use only the visible layers)
- geometry - The geometry used to select features to identify.
- layerIds - an array of layer ids which the Identify operation will be performed on. These can either be gotten from the map service documentation or the layerInfo property of an AGSDynamicMapServiceLayer.
- mapEnvelope - the extent or bounding box of the map view currently being viewed.
- spatialReference - the spatial reference of the map view.
- dpi - the dpi property can be ignored for now.
The following is an example of setting up the AGSIdentifyParameters object:
//the layer we want is layer ‘5’ (from the map service doc)
identifyParams.layerIds = [NSArray arrayWithObjects:[NSNumber numberWithInt:5], nil];
identifyParams.tolerance = 3;
identifyParams.geometry = mapPoint;
identifyParams.size = self.mapView.bounds.size;
identifyParams.mapEnvelope = self.mapView.envelope;
identifyParams.returnGeometry = YES;
identifyParams.layerOption = AGSIdentifyParametersLayerOptionAll;
identifyParams.spatialReference = self.mapView.spatialReference;
Executing the task
Executing the task is actually quite simple. Once you have the task created and have created and setup your AGSIdentifyParameters object, you simply need to call the executeWithParameters method on your Identify task.
//execute task...
[self.identifyTask executeWithParameters:identifyParams];
The task will automatically display the network activity indicator to indicate that it is waiting for results of the operation.
Retreiving the results
To get the results from the Identify task, your view controller will need to implement the AGSIdentifyTaskDelegate protocol. AGSIdentifyTaskDelegate has two methods:
- (void)identifyTask:(AGSIdentifyTask *) identifyTask operation: (NSOperation *) op didExecuteWithIdentifyResults:(NSArray *) results {
}
- (void)identifyTask:(AGSIdentifyTask *) identifyTask operation: (NSOperation *) op didFailWithError:(NSError *) error {
}
identifyTask:didExecuteWithIdentifyResults gets called if your task executed successfully. identifyTask:didFailWithError gets called if there were problems executing the task.
In addition to implementing the methods above, you will need to have set the delegate property of the Identify task to self as mentioned in the “How to create an Identify task” section. This will ensure that your AGSIdentifyTaskDelegate methods get called.
The results parameter in identifyTask:didExecuteWithIdentifyResults is an array of AGSIdentifyResult objects. The AGSIdentifyResults class has properties for the display field name of the result, the layer id, the layer name, and the feature. The feature is actually an AGSGraphic object containing the geometry of the result. Note that the AGSGraphic object does not have an associated symbol. It is up to you to set the symbol property if you are going to draw the graphic.
The following is an example of the identifyTask:didExecuteWithIdentifyResults method. First, it turns of the network activity indicator. Then it clears the previous results from our graphics layer. Then it loops through the result array, getting all of the graphics from the array (via the AGSIdentifyResult feature property) and assigning symbols to each graphic. The graphics are then added to the existing graphics layer in order to draw them on the map.
- (void)identifyTask:(AGSIdentifyTask *) identifyTask didExecuteWithIdentifyResults:(NSArray *) results
{
//clear previous results
[self.gLayer removeAllGraphics];
//add new results
AGSSymbol* symbol = [AGSSimpleFillSymbol simpleFillSymbol];
symbol.color = [UIColor colorWithRed:0 green:0 blue:1 alpha:0.5];
for (AGSIdentifyResult* result in results) {
result.feature.symbol = symbol;
[self.gLayer addGraphic:result.feature];
}
//call dataChanged on the graphics layer to redraw the graphics
[self.gLayer dataChanged];
}
The AGSGraphic object represented by the feature property of the AGSIdentifyResult also contains the attributes associated with the feature identified. These attributes are stored in an NSDictionary object inside the attributes property of the graphic.
Handling execution errors
Sometimes, for various reasons, the task execution will not complete successfully. In these situations, the identifyTask:didFailWithError method will be called. This method passes both the Identify task object along with an NSError object containing the reason for the failure. Below is a typical identifyTask:didFailWithError implementation.
- (void)identifyTask:(AGSIdentifyTask *) identifyTask didFailWithError:(NSError *) error
{
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Identify Error" message:[error localizedDescription] delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
[alert show];
[alert release];
}
This method simply displays a UIAlertView with the error information contained in the NSError object.