Overview

A map is basically an empty canvas onto which one or more layers are drawn. A wide variety of pre-defined layers are provided by the API.

Layer types

Most layers display content from GIS server web services, such as ArcGIS Server services, Bing Maps, Open Street Map, etc. These layers fall into two broad categories – dynamic layers and tiled layers.

Dynamic layers rely on web services that generate map images on-the-fly when requested by a client. Tiled layers rely on web services that provide map images that have been generated ahead of time based on some tiling scheme . Tiled layers provide much better performance than dynamic layers because map images do not need to be generated when requested by the client, instead map images are readily available and only need to be transferred to the client.

A Graphic layer is a special type of dynamic layer. It does not rely on any web service for its content. Its content is made up of graphics that are added to the layer.

Adding Layers to the Map

To add a layer to a map, you need to

1) Instantiate the layer. If the layer relies on a web service, you need to provide the URL of the service. If the web service is secured, you will also need to provide the necessary credentials to access the service.

NSURL* url = [NSURL URLWithString: @" http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"];
AGSTiledMapServiceLayer* layer = [AGSTiledMapServiceLayer tiledMapServiceLayerWithURL: url];

2) Add the layer to the map view using the addMapLayer:withName: method. By default, the layer is added on top of any existing layers. Layers are drawn in a bottom-up order. This means that a layer can potentially obscure the contents of other layers beneath it. If you wish to insert the layer at a specific position, you can use the insertMapLayer:withName:atIndex: method where an index of 0 will insert the new layer at the bottom. You need to provide a unique name while adding or inserting a layer. The map uses this to keep track of the layer incase you want to retrieve it later.

UIView<AGSLayerView>* lyrView = [mapView addMapLayer:layer withName:@"Streets"];

Once the layer is successfully added, its content will begin appearing in the map.

Accessing Layer properties

If a layer relies on a web service, it connects to the service in the background when instantiated. The service usually provides, among other things, default values for the layer's properties. For example, an AGSTiledMapServiceLayer connects to an ArcGIS Server Map service to get information about the extent, tiling scheme, etc. Layer properties are initialized only after a response is recieved from the service. Depending upon factors such as the time a service takes to respond, the quality of the network connection, and so on, it may take a while before a layer's properties are fully initialized.

When a layer is succcessfully initialized, its loaded property is enabled. This means that the layer successfully contacted its web service, if it needed to, and recieved a valid response. It also indicates that all properties on the layer have been fully initialized. Every layer broadcasts a LayerDidLoad or LayerFailedToLoad notification to indicate whether or not it loaded properly. Observers interested in these notifications can register for them using the default NSNotificationCenter.

Verifying the Layer was added

Layers connect to web services in the background. They do not block the thread on which they were added to a map. Hence, you should not assume that a layer was successfully added to a map when the addMapLayer:withName: or insertMapLayer:withName:atIndex: methods complete.

A map informs its delegate when a layer is successfully added or if an error is encountered while adding a layer. If a layer is successfully added, it also implies that it is fully initialized. To be notified of either of these events, you must set one of your classes as the map’s delegate. You do this by making your class (typically the view controller which manages the map) adopt the AGSMapViewLayerDelegate protocol.

@interface MyViewController : UIViewController <AGSMapViewLayerDelegate> 
   ...
@end

The delegate class must also implement one or more methods defined in the protocol which pertain to the operation being performed. For example, the class must implement the mapView:didLoadLayerForLayerView: method to be notified when a layer is successfully added. Similary, in order to be notified when an error is encountered while adding a layer, the class must implement the mapView:failedLoadingLayerForLayerView:withError: method.

@implementation MyViewController
  - (void) mapView:(AGSMapView*) mapView didLoadLayerForLayerView:(UIView<AGSLayerView>*) layerView {
  	NSLog(@"Layer added successfully");   
  }	 

  - (void) mapView:(AGSMapView*) mapView  failedLoadingLayerForLayerView:(UIView<AGSLayerView>*) layerView withError:(NSError*) error {
     NSLog(@"Error: %@",error);
  }
@end

Finally, an instance of the class must then be set as the map’s layerDelegate. This will allow the map to inform the class when a layer is successfully added or not..

mapView.layerDelegate = self;

Once the layer is successfully added, its content will begin appearing in the map, and you can safely access the layer's properties.

Layer View objects

After adding or inserting a layer, a map returns a handle to a Vew object. This view object implements the AGSLayerView protocol and is responsible for displaying the layer’s contents on the screen. You should keep a reference to this view object if, for instance, you intend to adjust the layer’s transparency or hide the layer.

UIView<AGSLayerView>* lyrView = [mapView addMapLayer:layer withName:@"Streets"];

//hide the layer
lyrView.hidden = YES; 

//or make it semi-transparent
lyrView.alpha = 0.5 ;
The layer view object exposes properties called drawDuringPanning and drawDuringZooming. It is recommended that you enable these properties of the bottom-most layer’s view to get the best user experience while navigating the map. When these properties are enabled, the map will attempt to display the layer's content even while the user is navigating the map. Frequently redrawing the layer consumes CPU cycles and could reduce the battery life of the device. Hence, enabling this behavior only for the bottom most tiled layer should provide a good balance of performance and user-experience.
lyrView.drawDuringPanning = YES;
lyrView.drawDuringZooming = YES;

The layer view object also exposes an error property. This property provides information about errors encountered during normal functioning of the layer. For example, if the network suddenly became unavailable, or if the credentials used to access a secured service stopped working. You can attach a Key-Value observer to this property to get notified when a layer encounters an error. Refer to Apple's Key-Value Observing Programming Guide for more information.

Map's spatial reference

The first layer you add to a map is considered to be the basemap layer. It dictates the overall spatial reference of a map. Any tiled layers you subsequently add to a map must also be in this spatial reference, otherwise their content will not be displayed. Dynamic layers, on the other hand, can be in any spatial reference. They will automatically re-project their content, if necessary, into the map's spatial reference.

12/7/2011