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 in their applications and configure it based on their needs.

The map component in the API, AGSMapView, shields developers from 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 available in the map's gps property. Be sure to 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

The map will automatically respond to location updates as promptly as possible, and appropriately udpate the position of the location symbol.

If you enable the autoPan property, the map will try to re-center itself on the device's location whenever the location symbol comes close to the edges of the map.

self.mapView.gps.autoPan = true;

If the user navigates the map while it's trying to re-center itself, autoPan will automatically be disabled so that the user does not have to "fight" with the map.

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

By default, the map uses a blue, round symbol to display the device's location. But you can change the symbol by using your own PNG images. The images must be named "GpsDisplay.png" and "GpsDisplayHeading.png" and they must be included in the application bundle. The images must 35x35 pixels for devices without retina display. It is recommended that you also include high resolution version of these images (70x70) pixels for devices with retina display and name them "GpsDisplay@2x.png" and "GpsDisplayHeading@2x.png"

Location symbol images
Images for location symbol
NoteNote:

Image names are case-sensitve.

If heading information is available from the location service, the map will use "GpsDisplayHeading.png" to display the location. The map will also automatically rotate the image by an amount specified by the heading to display the direction in which the device is travelling. To ensure the image points in the right direction when rotated, the symbol you use in "GpsDisplayHeading.png" should be pointing straight up by default.

Without heading
Symbol showing location only
With Heading
Symbol showing location and heading

Heading information is usually only available when the device is moving at some non-trivial velocity. If heading is not available, the map falls back to using "GPSDisplay.png". If this image is also not available, the map uses the default symbol.

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.

9/14/2011