Divesh Goyal
Recent Posts
10.1.1 Update 1 for ArcGIS Runtime SDK for iOS now available!
First off, thanks to everyone who came out to the Esri International Developer Summit in Palm Springs. It was great to meet you, share in your passion for technology, and get clear and direct feedback from you.
Some of you at the conference reported to us performance issues you were experiencing in your iOS apps after upgrading to version 10.1.1 of SDK. Some of these issues have also been previously reported on the user forums. We’re happy to announce today that we have an update that will greatly improve performance of your iOS apps by reducing memory and CPU utilization of the display subsystem. You can download the update here.
To our international users, we would also like to point out that this update adds translations for 6 new languages – Danish, Estonian, Hebrew, Latvian, Lithuanian, and Portuguese (Portugal).
We encourage you to try out the update and let us know how things go. As always, we’ll be listening.
Version 10.1.1 of ArcGIS Runtime SDK for iOS now available!
At the start of this new year, we’re happy to announce that a new version of ArcGIS Runtime SDK for iOS is now available. . This release adds support for commonly requested functionality such as advanced military symbology, secure communication using PKI client certificates, simulating location updates, sorting and grouping query results, and much more. You can download the SDK here.
ArcGIS Runtime SDK for iOS v2.3.2 Released : iOS 6 support for your apps
Apple recently revealed the iPhone 5 and iOS 6 with much fanfare at their media event on Sep 12th. iOS 6 became available to the general public a week later, and Apple stores started selling the first iPhone 5 devices today. The long lines outside the Apple stores prove once again that Apple has a hit on their hands, and approximately 15% of users had already upgraded their devices to iOS 6 on the first day of its release. It is apparent that users are moving up to iOS 6 and no doubt, they will want to take their apps with them.
Version 2.3 of ArcGIS Runtime SDK for iOS now available
It’s only been a couple of months since we pushed out our last release, but here we are again with another release because we wanted to share with you some of the exciting work we’ve done since then.
ArcGIS Runtime SDK for iOS Update 2.2.1 now available
This update contains a minor fix to the SDK installer. The v2.2 installer was unnecessarily laying down files related to ArcGIS Project Templates for XCode. As many of you might recall, these templates were deprecated and removed back at v2.1.
In majority of the cases, the laying down of these template files did not cause any harm. However, in exceptional cases, users were not able to install the v2.2 SDK due to permission issues related to where the files were being written. Even worse, the templates were being recognized by XCode giving users the false impression that ArcGIS project templates were still available and supported in v2.2. We would like to clarify that these templates are legacy, left over from the pre-v2.1 days.
The 2.2.1 installer has been fixed to not lay down the templates. There is no change to the API or the functionality.
Version 2.2 of ArcGIS Runtime SDK for iOS Released
On the heels of yet another engaging Developer Summit, we are happy to announce that v2.2 of ArcGIS Runtime SDK for iOS is now available for download from the resource center. Some of the improvements made in this release include -
- Ability to search for and access content, users, and groups on portals such as ArcGIS.com
- Support for WMS layers
- Conversion to and from Military Grid Reference System (MGRS) coordinates
- Improved performance of geometric operations using AGSGeometryEngine.
- Better handling of “No Data” tiles for tiled layers
- Faster loading of popups
- Faster rendering of graphics
- and much more…
You can refer to the documentation for more information about these improvments and how to migrate your existing applications to the new SDK.
For all of you who made it out to Palm Springs for the Developer Summit, thank you for coming and attending the sessions. We will soon make the iOS application that was shown in the plenary and tech sessions available as a sample on the resource center. We hope to see you again at this year’s User Conference in San Diego.
Contributed by Divesh Goyal of the ArcGIS for iOS Development Team
ArcGIS API for iOS v2.1 now available
We are happy to announce that v2.1 of ArcGIS API for iOS (henceforth referred to as ArcGIS Runtime SDK for iOS) is now available.
This release builds on the support for iOS 5 provided by v2.0.1 and includes additional functionality such as -
- Ability to view map content using ArcGIS 10.1 tile packages (*.tpk files) even when the device is offline.
- New GPS auto panning modes for vehicle navigation and compass navigation
- Flexible callout positioning
- Ability to rotate the map
- ..and much more
You can refer to the documentation for more information about what’s new at v2.1 and how to migrate your existing applications.
Contributed by Divesh Goyal of the ArcGIS for iOS Development Team
ArcGIS API for iOS Update 2.0.1 now available
We are sure that most of you are eager to start developing with Apple’s iOS 5 SDK. We are too. Some of you have already started using the Beta versions of iOS 5 SDK and have experienced problems in using it with ArcGIS API for iOS.
Based on your feedback, and to give you sufficient time to ready your applications in anticipation of supporting iOS 5, we have released update 2.0.1 to specifically resolve the issues you reported with iOS 5. You can download the update here.
Functionally, 2.0.1 is exactly the same as 2.0. The API remains unchanged too. If you have already migrated your applications to use 2.0 , migrating to 2.0.1 is as simple as uninstalling the old API package, installing the new one, and rebuilding your application.
At the time of releasing this update, Beta 7 was the most recent iOS 5 version available and used in our testing. Note that iOS 5 SDK is still only in Beta and it is possible that future versions could reveal new problems. We will strive to address those issues, should they come up, in a timely manner, however, bear in mind that we cannot truly claim to support iOS 5 until its final version is released.
So, with that said, download the update and start running your applications with iOS 5. And continue to send us your feedback, we look forward to hearing from you.
Contributed by Divesh Goyal of the ArcGIS for iOS Development Team
Developing a custom tiled layer
Introduction
ArcGIS API for iOS provides a number of predefined layers that work with GIS Servers such as ArcGIS Server, Bing Maps, etc. These layers retrieve map images from the GIS Server and display them on a map. Layers can be broadly categorized into two types – Dynamic layers and Tiled layers. Dynamic layers display maps using images that are generated on the fly. Tiled layers display maps using pre-generated map images, also known as tiles. These tiles are usually hosted on a server and can be accessed via a URL. The format for the URL depends upon the tiling scheme used by the provider to organize the tiles.
The API also provides an extensible framework that allows you to develop your own custom layers. In this post, we will focus on developing a custom tiled layer. Instead of accessing tiles from a server, our layer will use tiles that are bundled with the application. For the sake of brevity, we will only discuss the high-level aspects of creating the layer. The full implementation of the layer is available as a sample.
Map Cache
To use the custom layer, a map cache needs to be embedded in the application bundle.
A map cache contains map images. These images are organized within folders representing Levels and Rows. The name of the image files represent Columns. Names for Level folders begin with the letter ‘L’ followed by a number in decimal format. Names for Row folders and Column images begin with a letter (R for row, and C for column) followed by a number in hexadecimal format. For example, Level 11 is represented by L11 and Row 11 by R0000000b. The cache also contains two XML files – conf.xml and conf.cdi. These files contain metadata about the cache such as the tiling scheme and the full extent.
Note, if your cache was generated with a 9.3.1 ArcGIS Server or older, it may not contain the conf.cdi file. You need to upgrade the service to ArcGIS Server 10. This will automatically create the file for your existing cache.
Also note, ArcGIS Server 10 supports two cache formats – Compact and Exploded. The custom layer discussed in this post only works with exploded cache format.
When you include a cache in your application, be sure to include the entire folder hierarchy of the cache, starting with the top-level folder. The top-level folder usually has a name beginning with “cache_”. The top-level folder contains a folder whose name matches the data frame in the map document which was used to create the cache. The data frame folder usually contains a folder called “_alllayers” In the example shown, “cache_World” is the top-level folder and “Layers” is the data frame folder.
To add a cache to your application, right-click on the Other Sources group in your XCode project, choose Add > Existing Files. Navigate to the top-level map cache folder. Enable Copy items into destination group’s folder, and select the Create folder references for any added folders option. Click Add to finish.
Note: If you have large number of tiles, it may take a lot of time to copy them into the project directory. To avoid this delay, you can disable the Copy items into destination group’s folder option when adding the cache to your application. By doing this, the cache will still get included in your application bundle, but XCode will skip copying it to your project directory.
Map caches can be quite large depending upon factors such as the extent and scale levels of the cache. The size of your application could increase dramatically by including the cache. iOS applications can be as large as 2GB but the application must be under 20MB to allow over-the-air downloads. See the ITunes Connect Developer Guide for more information.
Design
All tiled layers in ArcGIS API for iOS extend from the AGSTiledLayer class. This class in-turn extends from AGSLayer. AGSTiledLayer and AGSLayer provide a lot of supporting infrastructure for implementing tiled layers. By inheriting from these classes, we can focus exclusively on the aspects that are unique to our layer. We don’t need to worry about, for instance, positioning tiles correctly on the map, or scaling tiles in response to a pinch. All we need to do is provide some metadata about the layer and implement the mechanism for retrieving tiles.
To create our custom layer OfflineTiledLayer, we too will extend from AGSTiledLayer.
| @interface OfflineTiledLayer : AGSTiledLayer { … } |
Any layer that extends AGSTiledLayer must provide information about its tiling scheme and implement the mechanics to retrieve tiles. The tiling scheme is used by the map to calculate which tiles fit within the map’s bounds. The map then requests the layer to fetch those specific tiles that need to be displayed.
| @implementation OfflineTiledLayer -(AGSTileInfo*) tileInfo { //todo } -(NSOperation<AGSTileOperation>*)retrieveImageAsyncForTile:(AGSTile*) tile { //todo } … @end |
By virtue of extending AGSTiledLayer, a layer also indirectly extends AGSLayer. The layer needs to provide some basic information such as it’s fullEnvelope, initialEnvelope, spatialReference, and units. AGSLayer defines read-only properties for these parameters. Our custom layer implements getter methods for these properties -
| @implementation OfflineTiledLayer … -(AGSUnits) units { //todo } -(AGSSpatialReference*) spatialReference { //todo } -(AGSEnvelope*) fullEnvelope { //todo } -(AGSEnvelope*) initialEnvelope { //todo } @end |
Finally, our layer defines an initialization method that requires a path to the data frame folder in the cache. The method also accepts a reference to an error object so that it can return an error if problems are encountered while reading the cache.
| @interface OfflineTiledLayer : AGSTiledLayer { - (id)initWithDataFramePath:(NSString*)path error:(NSError**)outError; } |
Implementation
The following diagram provides an overview of how the OfflineTiledLayer works. To cleanly separate responsibility, the layer uses a dedicated class called OfflineCacheParserDelegate to parse the XML files in the cache. To actually retrieve tiles from the cache, the layer uses objects of an OfflineTileOperation class.

The bulk of the work is done during layer initialization. This is when the layer uses OfflineCacheParserDelegate to parse metadata in the conf.xml and conf.cdi XML files. These files contain information about the layer’s tiling scheme and extent respectively.
| - (id)initWithDataFramePath: (NSString *)path error:(NSError**)outError { … OfflineCacheParserDelegate* parserDelegate = [[OfflineCacheParserDelegate alloc] init]; //Parse the conf.cdi file NSString* confCDI = [[NSBundle mainBundle] pathForResource:@”conf” ofType:@”cdi” inDirectory:_dataFramePath]; NSXMLParser* xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:[NSURL fileURLWithPath:confCDI]]; [xmlParser setDelegate:parserDelegate]; [xmlParser parse]; [xmlParser release]; //Parse the conf.xml file ofType:@”xml” inDirectory: _dataFramePath]; xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:[NSURL fileURLWithPath:confXML]]; [xmlParser setDelegate:parserDelegate]; [xmlParser parse]; [xmlParser release]; … } |
OfflineCacheParserDelegate decodes the information and makes it available as AGSTileInfo and AGSEnvelope objects. The layer then uses these objects for implementing the properties defined in AGSLayer and AGSTiledLayer. Finally, the layer indicates it is loaded by invoking the layerDidLoad method.
| - (id)initWithDataFramePath: (NSString *)path error:(NSError**)outError { … _tileInfo = [[parserDelegate tileInfo] retain]; _fullEnvelope = [[parserDelegate fullEnvelope] retain]; [self layerDidLoad]; … } - (AGSTileInfo*) tileInfo { return _tileInfo; } - (AGSEnvelope*) fullEnvelope { return _fullEnvelope; } … |
When the layer is added to the map, the map requests for tiles that need to be displayed within the map’s bounds. For each tile, the map invokes the layer’s retrieveImageAsyncForTile: method. To improve performance, tiled layers use an operation queue for retrieving tiles. This operation queue is provided by the parent AGSTiledLayer. The queue allows multiple tiles to be retrieved concurrently in the background. A tiled layer creates an operation object for every tile that needs to be fetched and adds it to the queue. The queue then runs these operations and removes them when they finish executing. Operation objects used by tiled layers must conform to the AGSTileOperation protocol.
OfflineTiledLayer uses a custom class, OfflineTileOperation, to retrieve tiles from the local cache. The operation object is given information about which tile to retrieve, the path to the local cache, and a target-action pair representing the method to invoke when the operation finishes.
| - (NSOperation<AGSTileOperation> ;*) retrieveImageAsyncForTile: (AGSTile*) tile { //Start an operation to fetch the tile OfflineTileOperation *operation = [[OfflineTileOperation alloc] initWithTile:tile dataFramePath:_dataFramePath target:self action:@selector(didFinishOperation [super.operationQueue addOperation return [operation autorelease]; } |
When the operation finishes, it invokes the didFinishOperation: method on the layer. The layer then checks to see whether the operation found a tile image or not. It then appropriately notifies the tileDelegate. The tileDelegate ensures that the tile is correctly displayed on the map.
| - (void) didFinishOperation:(NSOperation<AGSTileOperation>*)op { //Check if a tile was found… if (op.tile.image!=nil) { //… inform the delegate of success [self.tileDelegate tiledLayer:self operationDidGetTile } else { //… inform the delegate of failure [self.tileDelegate tiledLayer:self operationDidFailToGetTile } } |
Summary
In this post we saw how to develop a custom tiled layer that reads tiles from a map cache embedded within the application. To use the layer with your own data, you need to publish the data as a map service on ArcGIS Server and then create a cache for the service. You can then copy the cache over to your development machine and include it in your iOS application.
Once the cache and the custom layer are included in your application, all you need to do is instantiate the layer with a path to your cache’s data frame folder and then add the layer to the map -
| NSError *err; NSString *dataFramePath = @”cache_World/Layers”; //Path to your cache OfflineTiledLayer *tiledLayer = [[OfflineTiledLayer alloc] initWithDataFramePath: dataFramePath error: &err]; … UIView *tiledLayerView = [self.mapView addMapLayer:tiledLayer withName:@"Custom Tiled Layer"]; |
Contributed by Divesh Goyal of the ArcGIS for iOS Development Team
Using the ArcGIS API for iOS Samples
As most of you already know, we provide a number of samples for ArcGIS API for iOS under the iOS Developer Samples group on www.arcgis.com. These samples showcase the functionality of the API and also to help you get started developing applications of your own. Be sure to check the group regularly for updates and new additions, and also send us your ideas about which samples you would like to see.
Some of you have complained about not being able build and run the samples. In this post, I will provide a couple of tricks that could help you troublshoot problems with the samples, and also point you to key Apple resources for more information about the iOS Development environment.
Eash sample is provided as a zip file. The zip file contains an entire XCode project including the source code, graphics, and XCode-specific project files. The project files store many common build settings such as the frameworks and libraries to link to, the SDK to use, the targets to build, and so on.
Most commonly when a sample doesn’t build properly, the Overview Toolbar menu will display Base SDK Missing.
This means the project is trying to reference an iOS SDK that is not available on your machine. This might happen, for instance, if you installed a more recent version of the iOS SDK than what was used to create the sample. When we create samples, we use the most recent version of the iOS SDK available at the time. Thus, when created samples for version 1.0 of the API, we used iOS 4.0 SDK to create the samples. Information about the SDK being used is stored in the project files. Shortly thereafter, Apple released iOS 4.1, and more recently, 4.2 SDKs. If you have these SDKs installed on your machine instead, you will experience the problem described above because the sample will try to unsuccessfully reference the previous version of the SDK.
To fix the problem, you need update the Base SDK. You do this by double-clicking the project’s Target to bring up the Info window. Then, under the Build settings pane, update the Base SDK property.
One thing to consider when you’re making changes to a Target, is to make sure you are modifying the correct configuration. A target has 2 configurations by default – Release and Debug. These configurations are used to build the Release and Debug versions of your application respectively. Some settings, such as the Base SDK, typically use the same values for both configurations. When you modify such settings, remember to modify the settings for each configuration. You can do this either by modifying each configuration separately, or by modifying both configurations simeltaneously by selecting the All Configurations option.

Another common reason why a sample may not run is if the project is configured to run the sample on a device. In such cases, you can expect to encounter the following error –

The simplest way to run a sample, is to run it on the simulator. You can do this by choosing the Simulator option in the Overview toolbar menu.
If you really do want to run on a device, you will need to do a few things –
1. You will need to have a valid Development Certificate from Apple. This certificate needs to be installed on your development machine.
2. You will also need to create a Development Provisioning Profile from the iOS Provisioning Portal and install it on your development machine and each iOS device you intend to use. A provisioning profile is used to authorize an application (specified by an App ID) created by a developer (specified by a developer certificate) to run on a device (specified by device IDs). You can find more information about this process in the Managing Devices and Digital Identities section of the iOS Development Guide and also in the iOS Developer Program User Guide (Note, you will need to sign in with your Apple ID to access the User Guide).
You will also need to make a few changes to the project -
3. You will need to modify the sample’s *-Info.plist file under the Resources group. In this file, you will need to modify the Bundle Identifier property and replace the “com.yourcompany” text with the App ID used in your provisioning profile.
4.You will need to digitially sign the application. Open the Target’s build settings, scroll down to the Code Signing Identify section, and choose your provisioning profile to digitally sign the application.

Apple’s Technical Note TN2250 has more information about the Code Signing process.
Once you’ve completed these steps, ensure your device is connected to your development machine, then build and run the project. The sample application should automatically get installed and launched on your device.
