Displaying location on the map

Many iOS devices such as iPod Touch, iPad, and the iPhone provide information about the device's location. iOS includes a framework known as "CoreLocation" that abstracts how the location is retrieved, whether through Wi-Fi, cellular networks, or GPS. The framework also provides an API for developers to incorporate location capabilities into their applications and configure it based on their needs.

The map component, AGSMapView, shields developers from dealing with the complexity of the CoreLocation framework and provides an easy way to display and track the device's location on the map. The AGSGPS object associated with the map provides a simple façade over the CoreLocation framework and greatly simplifies working with location services.

Start displaying location

To start displaying the device's location on the map, you need to invoke the start method on the AGSGPS object. You should invoke this method only after the map has finished loading, for example, in the mapViewDidLoad: delegate method of AGSMapViewLayerDelegate protocol

-(void) mapViewDidLoad:(AGSMapView*)mapView {
 	[self.mapView.gps start];
}

By default, the map uses a blue, round symbol to display the device's location. The map will always try to get most accurate location available. Depending upon signal strength, satellite positions, and other factors, the location reported could be a best possible approximation. The map displays a blue-circle around the location symbol to indicate the range of accuracy.

Default Location Symbol
Default symbol showing location

As the device moves, the map will respond to location updates and appropriately update the position of the location symbol.

Autopan Modes

The map provides a number of presets that define how the map behaves when location updates are received.

Off

In this mode, it is possible that the symbol may move off screen in response to location updates. When this happens, the map does not pan to bring the location symbol back in view.

Default

In this mode, the map attempts to always keep the location symbol on-screen. It does this by re-centering on the location symbol whenever the symbol moves outside the "wander extent". Thus, the location symbol may move freely within the wander extent, but as soon as the symbol exits the wander extent, the map re-centers on the symbol.

You can specify a wander extent by modifying the wanderExtentFactor on AGSGPS. A value of 1 implies a wander extent equal to the size of the map's viewable extent and that the location symbol may move right up to the edge of the map before the map recenters. A value of 0 implies an infinitesimal wander extent and that the map should recenter on the location symbol for every location update. By default, the wander extent is half the size of the map's viewable extent,

self.mapView.gps.autoPanMode = AGSGPSAutoPanModeDefault ;
self.mapView.gps.wanderExtentFactor = 0.75; //75% of the map's viewable extent

If a user pans the map in this mode, the mode automatically changes to OFF to prevent the user from having to "fight" with the map which may otherwise try to re-center based on future location updates.

Navigation

This mode is best suited for in-vehicle navigation. In this mode, the location symbol is pinned to a point on the screen, and it always points towards the top edge of the device. The map is panned and rotated based on location updates and the direction the device is travelling in. Thus, the location symbol appears stationary, while the map underneath it appears to be moving and rotating.

The position of the location symbol can be adjusted by modifying the navigatonPointHeightFactor property on AGSGPS. A value of 0 implies the location symbol should be positioned at the bottom edge of the map, and 1 implies the top edge. A value between 0 and 1 positions the symbol somewhere along the center line from the bottom edge to the top edge.

self.mapView.gps.autoPanMode = AGSGPSAutoPanModeNavigation ;
self.mapView.gps.navigationPointHeightFactor  = 0.25; //25% along the center line from the bottom edge to the top edge

If a user pans the map in this mode, the mode automatically changes to OFF.

Compass Navigation

This mode is better suited when the user is walking. Just as in Navigation mode, in this mode too the location symbol is pinned to a point on the screen, and it always points towards the top edge of the device. However, the map is rotated based on the user's bearing relative to the magnetic north, and not based on the direction the device is travelling in as is the case in Navigation mode. Thus, the map will reflect what lies ahead of the user as the user pivots around his/her location.

The position of the location symbol can be adjusted by modifying the navigatonPointHeightFactor. A value of 0 implies the location symbol should be positioned at the bottom edge of the map, and 1 implies the top edge. A value between 0 and 1 positions the symbol somewhere between the bottom and top edges.

self.mapView.gps.autoPanMode = AGSGPSAutoPanModeCompassNavigation ;
self.mapView.gps.navigationPointHeightFactor  = 0.5; //50% along the center line from the bottom edge to the top edge

If a user pans the map in this mode, the mode automatically changes to OFF.

NoteNote:

If your application allows the device interface orientation to change, you should pass the new orientation to the AGSGPS object so that it can appropriately reposition the location symbol.

Stop displaying location

To stop displaying the device's location, you need to invoke the stop method.

[self.mapView.gps stop];

Customizing the location symbol

The SDK provides 3 images that are used for the location symbol by default. These images named "GpsDisplay.png" , "GpsDisplayHeading.png", and "GpsDisplayCompass.png" are included in the ArcGIS.bundle.

Without heading
GpsDisplay.png: Symbol showing location only
With Heading
GpsDisplayHeading.png: Symbol showing location and heading
With bearing
GpsDisplayCompass.png : Symbol showing location and compass bearing

Depending upon the AutoPanMode in use, and the type of information provided by the location updates, one of the default images will be used for the location symbol.

In Off, Default, and Navigation modes, the "GpsDisplay.png" image will be used if only location information is available and "GpsDisplayHeading.png" will be used if both location and course (direction of travel) information are available. In Off and Default modes, the "GpsDisplayHeading.png" image will be appropriately rotated by an amount specified by the course to display the direction in which the device is travelling, but in Navigation mode, the map will be rotated instead.

NoteNote:

Course information is only available when he device is moving at some non-trivial velocity. This is why the map typically only displays the "GpsDisplayHeading.png" symbol when the device is travelling in a vehicle.

In Compass Navigation mode, the "GpsDisplayCompass.png" image is used to display the device's location and bearing.

You can change the location symbol by providing your own PNG images. Your images must have the same name as the default images, and be part of your XCode project. The images in your Xcode project will be given precedence over the default ones provided in ArcGIS.bundle. Where possible, it is recommended that you also include high resolution version of your images for devices with retina display. You should name the high resolution versions "GpsDisplay@2x.png", "GpsDisplayHeading@2x.png", and "GpsDisplayCompass@2x.png".

Location symbol images
Images for location symbol
NoteNote:

Image names are case-sensitve.

Displaying location information in the callout

To display a callout when a user taps on the location symbol, you need to assign an infoTemplateDelegate for the map's AGSGPS object. You do this by making one of your classes adopt the AGSGPSInfoTemplateDelegate protocol.

@interface MyTemplate : NSObject <AGSGPSInfoTemplateDelegate> 
  ...
 @end

An instance of your class must also be set as AGSGPS object's infoTemplateDelegate. This will allow the map to invoke methods on your class and consult it before showing a callout.

MyTemplate* template = ... ;

self.mapView.gps.infoTemplateDelegate = template;
Finally, your class must implement one or more methods defined in the protocol to specify what content needs to be displayed in the callout. You can provide a title, detail, and/or image for the callout or you can entirely customize the callout's appearance by embedding a custom view.
@implementation MyTemplate 
  
  ...

  - (NSString*) titleForGPS: (AGSGPS*) gps screenPoint: (CGPoint) screen {
      NSLog(@"Location : %@", gps.currentPoint);
      return @"<title text>";
  }

  - (NSString*) detailForGPS:(AGSGPS*) gps screenPoint:(CGPoint) screen {
      NSLog(@"Location : %@", gps.currentPoint);
      return @"<detail text>";
  }

  - (UIImage*)imageForGPS:(AGSGPS *) gps screenPoint:(CGPoint) screen {  
     return [UIImage imageNamed:@"<image_for_the_callout>"];
  }

  /* //Only implement if you want to embed a custom view
  - (UIView*)customViewForGPS:(AGSGPS *) gps screenPoint:(CGPoint) screen {
   //create a view programatically, or load from nib file
  }
  */
@end

NoteNote:

If you embed a custom view in the callout, the title, detail, and image delegate methods are ignored. For more information on creating views programmatically and using Interface Builder, refer to Apple's View Programming Guide for iOS. You may also find it helpful to refer to Apple's Resource Programming Guide for information on how to programmatically load views from nib files.

Accessing location information

The AGSGPS object has two properties that provide the device's location.

The currentLocation property contains the location provided by the underlying CoreLocation framework. The coordinates are always in decimal degrees based on the WGS 84 coordinate system.

The currentPoint property contains the same location information, however, it is projected into the map's spatial reference.

Listening for location updates

The currentLocation and currentPoint properties on AGSGPS are KVO (Key-Value Observing) compliant. You can attach an observer to either of these properties in order to be notified when they are updated.

- (void)registerAsObserver {
  [ self.mapView.gps addObserver:self
                      forKeyPath:@"currentPoint"
                         options:(NSKeyValueObservingOptionNew)
                         context:NULL];
}

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {
  if ([keyPath isEqual:@"currentPoint"]) {
   NSLog(@"Location updated to %@", self.mapView.gps.currentPoint);
  }
}

For more information on KVO, refer to Apple's Key-Value Observing Programming Guide.

See Also

12/7/2011