Tasks are the foundation of the geospatial functionality in your iOS applications. Using tasks in your applications allows users to interact with maps, find and display reports of real world objects, collect geographic information, and analyze what they see on a map.
The ArcGIS Runtime SDK for iOS API includes the following tasks:
- Query Task—Get features from map services that satisfy attribute or spatial queries.
- Identify Task—Get features from map services at a location.
- Find Task—Get features from map services that contain a particular value in their attributes.
- GeometryService Task—Perform geometric operations such as buffering, projecting, and simplifying.
- Geoprocessor—Perform complex GIS analysis by executing geoprocessing models that have been published as geoprocessing services.
- Locator—Match locations to addresses and vice-versa.
- Route Task—Compute point-to-point or multipoint routes and driving directions.
- Service Area Task—Calculate areas that can be serviced (reached) from a given location.
- Closest Facility Task—Find facilities that are closest to a given incident.
Working with tasks
All tasks inherit from AGSTask. Working with tasks is simple once the pattern is understood. All tasks follow the same basic principles and pattern. Tasks are wrappers around operations supported by ArcGIS Server REST web services. Tasks take care of asynchronously sending the request, showing the network activity indicator, applying appropriate credentials to the network resource, and parsing the results.
To execute a task, you typically work through the following pattern:
- Set delegate
- Kick-off operation
- Wait for delegate to be fired
Since the tasks inherit from AGSTask, they all have the following initializers: initWithURL: and initWithURL:credential:. Since tasks rely on operations of ArcGIS Server REST web services, you must instantiate them with a URL. Some services will be secured and will require credentials.
When you create the task, you need to ensure its memory does not get deallocated before it has a chance to execute. To do this, you need to retain the task if you're using manual retain-release, or create a strong reference to it if you're using ARC. See Apple's Memory Management Programming Guide for more information on how to manage object memory.
Since tasks work asynchronously, the calling object will want to be notified when the task succeeds or fails. This is where the delegate comes in to play. The delegate is an object that you assign to the task, on which the task can call well-known methods (defined by some protocol). Typically, each operation that the task can execute will have a success method and a failure method. For example, the AGSQueryTaskDelegate has the following methods:
optional func queryTask(queryTask: AGSQueryTask!, operation op: NSOperation!, didExecuteWithFeatureSetResult featureSet: AGSFeatureSet!)
optional func queryTask(queryTask: AGSQueryTask!, operation op: NSOperation!, didFailWithError error: NSError!)
There are two methods (one success and one fail) for the query operation. When you set yourself as a delegate, you can choose to implement these methods if they're important to you.
To kick off an operation on the task, you call the method of the operation you want to execute. For example, the AGSQuery task has the following method:
func executeWithQuery(query: AGSQuery!) -> NSOperation!
Tasks return the operation they kick off, so you can cancel it at anytime. You can also associate these operations with some state, so that you can track which operations you kicked off. You can kick off as many operations as you like, even on a single task. For example, you can have one query task that executes five queries simultaneously.
Wait for delegate to be fired
After kicking off an operation, you can wait for the delegate to be notified of its success or failure. The task will show the network activity indicator for you while the operation is executing. If an operation fails, it may be because the proper credentials were not supplied, the inputs were not valid, or because of some other reason. You can check the NSError object that's returned to find out the exact cause of the error.
If your delegate methods are not being invoked when the task finishes execution, check to make sure that the task is not getting deallocated prematurely. You need to retain the task if you're using manual retain-release, or create a strong reference to it if you're using ARC.