ArcGIS SDK for iOS
Looking for another option for iOS maps? Try the ArcGIS maps for iOS. Some of features available include:
- Use any tile service that ArcGIS supports (including Bing)
- Add layers from any ArcGIS feature service
- Use tasks for common uses like geocoding/locating, routing/directions, and querying
- Enable collabartion via WebMaps
We have a more detailed discussion over here and a quick sample below.
Sample Code
This will put a call out on a Bing aerial map with labels. The first class,
LQPortlandAnnotation
serves as a data model for both MKAnnotation
purposes
(which aren't needed here) and an AGSInfoTemplateDelegate
for AGSGraphic
.
LQPortlandAnnotation.h
:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <ArcGIS/ArcGIS.h>
@interface LQPortlandAnnotation : NSObject <MKAnnotation, AGSInfoTemplateDelegate>
@end
LQPortlandAnnotation.m
:
#import "LQPortlandAnnotation.h"
@implementation LQPortlandAnnotation
@synthesize coordinate, title, subtitle;
- (LQPortlandAnnotation *)init
{
self = [super init];
if (self) {
coordinate = (CLLocationCoordinate2D){ 45.5236, -122.6750 };
title = @"Portland!";
subtitle = @"Yee haw!!!";
}
return self;
}
// convert instance variable from `CLLocationCoordinate2D`, which takes doubles
// of degrees for latitude and longitude, to `AGSPoint` in the "Web Mercator"
// spatial reference.
//
- (AGSPoint *)webMercatorPoint
{
AGSPoint *p = [AGSPoint pointWithX:self.coordinate.longitude
y:self.coordinate.latitude
spatialReference:[AGSSpatialReference wgs84SpatialReference]];
p = (AGSPoint *)[[AGSGeometryEngine defaultGeometryEngine] projectGeometry:p
toSpatialReference:[AGSSpatialReference webMercatorSpatialReference]];
return p;
}
// returns the same data as the `MKAnnotation` property
//
- (NSString *)titleForGraphic:(AGSGraphic *)graphic screenPoint:(CGPoint)screen mapPoint:(AGSPoint *)map
{
return self.title;
}
// returns the same data as the `MKAnnotation` property
//
- (NSString *)detailForGraphic:(AGSGraphic *)graphic screenPoint:(CGPoint)screen mapPoint:(AGSPoint *)map
{
return self.subtitle;
}
@end
Here is the actual controller class. The XIB has only one view in it,
AGSMapView
; and it is wired to the IBOutlet
below.
LQViewController.h
:
#import <UIKit/UIKit.h>
#import <ArcGIS/ArcGIS.h>
@interface LQViewController : UIViewController <CLLocationManagerDelegate>
@property (strong, nonatomic) IBOutlet AGSMapView *mapView;
@end
Finally, the implementation for the view controller. This zooms to the device's location, then shows a callout over Portland, OR.
LQViewController.m
:
#import "LQViewController.h"
@implementation LQViewController {
@private
CLLocationManager *locationManager;
AGSLayer *baseLayer;
LQPortlandAnnotation *pdx;
}
@synthesize mapView = _mapView;
- (void)viewDidLoad
{
[super viewDidLoad];
pdx = [LQPortlandAnnotation new];
baseLayer = [[AGSBingMapLayer alloc] initWithAppID:@"basemap" style:AGSBingMapLayerStyleAerialWithLabels];
[self.mapView addMapLayer:baseLayer withName:@"Basemap"];
self.mapView.wrapAround = YES;
locationManager = [CLLocationManager new];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
[locationManager startUpdatingLocation];
}
#pragma mark -
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSMutableArray *locations = [NSMutableArray arrayWithObject:newLocation];
if (oldLocation) [locations insertObject:oldLocation atIndex:0];
[self locationManager:locationManager didUpdateLocations:locations];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *location = [locations objectAtIndex:(locations.count - 1)];
if (location.horizontalAccuracy < 100.0) {
[self setExtent:location withDelta:0.025 animated:YES];
[locationManager stopUpdatingLocation];
[self createCallout];
}
}
- (void)setExtent:(CLLocation *)location withDelta:(float)delta animated:(BOOL)animated
{
CLLocationCoordinate2D latlng = location.coordinate;
AGSEnvelope *envelope = [AGSEnvelope envelopeWithXmin:(latlng.longitude - delta)
ymin:(latlng.latitude - delta)
xmax:(latlng.longitude + delta)
ymax:(latlng.latitude + delta)
spatialReference:[AGSSpatialReference wgs84SpatialReference]];
[self.mapView zoomToEnvelope:envelope animated:animated];
}
#pragma mark -
- (void)createCallout
{
static NSString *graphicsLayerKey = @"graphicsLayer";
id<AGSLayerView> lv = [self.mapView.mapLayerViews objectForKey:graphicsLayerKey];
AGSGraphicsLayer *graphicsLayer = (AGSGraphicsLayer *)lv.agsLayer;
if (!graphicsLayer) {
graphicsLayer = [AGSGraphicsLayer graphicsLayer];
[self.mapView addMapLayer:graphicsLayer withName:graphicsLayerKey];
}
AGSGraphic *dot = [AGSGraphic graphicWithGeometry:[pdx webMercatorPoint]
symbol:[AGSSimpleMarkerSymbol simpleMarkerSymbolWithColor:[UIColor blueColor]]
attributes:nil
infoTemplateDelegate:pdx];
[graphicsLayer addGraphic:dot];
[graphicsLayer dataChanged];
}
#pragma mark -
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)viewDidUnload {
[self setMapView:nil];
[super viewDidUnload];
}
@end