Navigating the map

The Map View includes options for defining and changing the map extent as well as the user experience when the extent is modified. It is important to note that the first layer in a Map's layer collection will define the follow properties for the map:

While initial extent can be modified, the spatial reference cannot be changed explicitly. This document will discuss both developer and end-user solutions for working with map extent.

Setting the map extent

To set the map extent, use the zoomToEnvelope:animated: method on the map view. Note that the map view needs to have been loaded before calling that method or the call will have no effect. You can use the mapViewDidLoad: method of the AGSMapViewLayerDelegate protocol to know when the map has been loaded and then set the initial map extent from there. The following steps describe the process of implementing the AGSMapViewLayerDelegate protocol and using the zoomToEnvelope:animated: map view method to set an initial map extent:

1. Add the AGSMapViewLayerDelegate protocol to the protocol list in your view controller's interface definition:

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

Note that all of the methods on the AGSMapViewLayerDelegate are optional, so you only have to implement the ones you are actually using.

2. In the view controller's viewDidLoad implementation, set the map view's layerDelegate property to self. This will allow the map view control to call any implemented methods of the AGSMapViewLayerDelegate protocol in your view controller.

self.mapView.layerDelegate = self;

3. Add the implementation for the AGSMapViewLayerDelegate mapViewDidLoad method in the view controller’s implementation (.m) file. This method will be called after the map view has been loaded. In mapViewDidLoad, define an AGSEnvelope describing the new map extent and call the map view’s zoomToEnvelope:animated: method to set the map extent:

- (void)mapViewDidLoad:(AGSMapView *)mapView {
//create extent to be used as default
 AGSEnvelope *envelope = [AGSEnvelope envelopeWithXmin:-124.83145667 ymin:30.49849464 xmax:-113.91375495  ymax:44.69150688  spatialReference:mapView.spatialReference];
 [self.mapView zoomToEnvelope:envelope animated:NO];
}

Now, after the map view has been loaded, the extent will be set to the coordinates of the envelope created.

Getting the map extent

You may not know the extent of the map until runtime. You can use the envelope property of the map view to get the extent of the map.

AGSEnvelope* mapExtent = self.mapView.envelope;

The map view must have been loaded for the envelope property to be valid.

Tracking panning and zooming

The Map View control provides two notifications for extent changes, MapDidEndPanning and MapDidEndZooming. These notifications are broadcast after the map has been panned or zoomed, respectively. The following code is an example of how to listen for notifications when the user pans or zooms the map. It displays an alert showing the new map extent retrieved from the envelope property of the map view:

- (void)MapViewDidLoad:(AGSMapView *)mapView  {

  // register for "MapDidEndPanning" notifications
  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(respondToEnvChange:)
    name:@"MapDidEndPanning" object:nil];

  // register for "MapDidEndZooming" notifications
  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(respondToEnvChange:) 
    name:@"MapDidEndZooming" object:nil];

  ...
}

// The method that should be called when the notification arises
- (void)respondToEnvChange: (NSNotification*) notification {

  //create the string containing the new map extent NSString*
  NSString* theString = [[NSString alloc] initWithFormat:@"xmin = %f,\nymin =
    %f,\nxmax = %f,\nymax = %f", mapView.envelope.xmin,
    mapView.envelope.ymin, mapView.envelope.xmax,
    mapView.envelope.ymax];

  //display the new map extent in a simple alert
  UIAlertView* alertView = [[UIAlertView alloc]	initWithTitle:@"mapViewDidEndPanning" 
    message:theString delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
  [alertView show];
  [alertView release];
  [theString release];

}

You should note that these notifications are broadcast when the processor is idle, thus there might be a slight delay between when the user finished performing the action and when the notification was raised. Also, notificatons are delievered on the main thread. You should not block this thread by pefroming expensive tasks otherwise your application will appear sluggish to the user.

Changing the map extent

As mentioned previously, you can use the zoomToEnvelope:animated: method on a map view to set a map view's extent. You can also center the map at a given point using the map view's centerAtPoint:animated: method:

AGSPoint *newPoint = [AGSPoint pointWithX:-93.032201 y:49.636213 spatialReference:self.mapView.spatialReference];
[self.mapView centerAtPoint:newPoint animated:NO];

User gestures

The user can perform several gestures which change the map view's extent at run-time. All of these will trigger either the MapDidEndPanning and MapDidEndZooming notifications.

User Action

Map Action

Notification raised

Pinch-In

Zoom out on map

MapDidEndZooming

Pinch-Out

Zoom in on map

MapDidEndZooming

Double Tap

Zoom in on map

MapDidEndZooming

Two finger Tap

Zoom out on map

MapDidEndZooming

Swipe (any direction)

Pan map in direction of swipe

MapDidEndPanning

9/14/2011