Apple received a LOT of flak for their undercooked Maps app. Luckily for iPhone users, Google swooped in to assert some dominance in the Maps department with their lovely Google Maps app. They launched the SDK earlier this year after initially rolling it out  to developers on a request basis only. Here is a simple guide on how you can add and use the Google Maps SDK in your project.

The first thing to note is that you need Xcode 4.5 (or greater) which runs iOS 6 (or later) to compile code from the SDK. Also, your test device needs to run atleast iOS 5.1. Unfortunately there still are plenty of users who haven’t migrated from iOS 5, myself included :-) .Code written for this particular SDK will crash on iOS 5. Hence it is prudent to include a check that ascertains which version of iOS the user has installed. You can always use

[sourcecode language=”objc”]
[[UIDevice currentDevice].systemVersion floatValue];
[/sourcecode]

Although I found a far more elegant solution through a StackOverflow post. Bless you O wise StackOverflow! Essentially create a header file called OSVersion.h by clicking File -> New File -> C and C++ in the left menu.

Throw in this code into the header file that you just created

 

[sourcecode language=”objc”]
#define SYSTEM_VERSION_EQUAL_TO(v)

([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)

#define SYSTEM_VERSION_GREATER_THAN(v)

([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)

([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

#define SYSTEM_VERSION_LESS_THAN(v)

([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)

#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)

([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
[/sourcecode]

Now you can include OSVersion.h in any file where you want to perform a check for your version of iOS.

Before you rush onto writing Maps code, do get an API key from here. API keys are specific to each API Google gives out and is mainly for them to track your usage. There are limits on how many API calls you can make to the maps server though. There is no limit to the number of map views on native maps APIs but you will probably use the Google Places API which has a limit of 1000 in every 24 hour period. You can increase that to 1,00,000 if you validate your account by giving your credit card number. Do note that you will NOT be charged for this. The credit card is merely a way to validate your account.

The official page for the SDK comprehensively describes how you can add the SDK to your project. Just follow the instructions meticulously and you will have added the SDK successfully. In my great hurry I did falter with point 4 so do ensure that “Copy items into destination folder is NOT selected”. If you are able to import GoogleMaps/GoogleMaps.h into your project you are good to go.

The good thing is Google has made it ridiculously easy to use this SDK. This code snippet will add a map View to your app. In your .h file declare

 

[sourcecode language=”objc”]
GMSMapView *mapView;
GMSMarkerOptions *options;
[/sourcecode]

Then in your .m file you can add this:

 

[sourcecode language=”objc”]
-(void) viewDidLoad {
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"5.1")) {
GMSCameraPosition *camera;
camera = [GMSCameraPosition cameraWithLatitude: 28.5667  longitude: 77.1166 zoom: 15];
mapView = [[GMSMapView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
[mapView setCamera:camera];
mapView.myLocationEnabled = YES;
[self.view addSubview:mapView_;
options = [[GMSMarkerOptions alloc] init];
options.position = CLLocationCoordinate2DMake(28.5667, 77.116699);
options.title = @"Delhi";
options.snippet = @"India";
[mapView addMarkerWithOptions:options];
}
else {
// Add MKMapView as you would usually do
}
[/sourcecode]

GMSCameraPosition is a class that determines the position and zoom level of the map. It is a required parameter for any mapView. The above code essentially draws a map in your view with an annotation (GMSMarkerOptions) that points to Delhi, India. If you click on the marker this is what you’ll see You can change the image of the marker by using the the ‘icon’ property. For example:

[sourcecode language=”objc”]

marker.icon = [UIImage imageNamed: @”blood-drop.png”];

[/sourcecode]

The above line of code references Tarams’ own product GiveBlood which you can check out at www.givebloodapp.com

Markers can be removed from the map by using the ‘clear’ method of the mapView. The below line of code will remove ALL markers from the map.

 

[sourcecode language=”objc”]
[mapView clear];

[/sourcecode]

If you want to remove a particular marker from the map you’ll have to maintain a reference to it. What I did was:

 

[sourcecode language=”objc”]
marker.tag = 42; // Set a tag to your marker where you declared it.

// Code to remove marker

for (UIView *tempMarker in [self.mapView markers]) {
if (tempMarker.tag == 42) {
[marker removeFromSuperview];
}
}

[/sourcecode]

You can change your map type to Normal, Hybrid, Terrain and Satellite. Use the ‘mapType’ property like so:

Here is how the Terrain map looks like:

That would conclude a basic tutorial on how you can use the Google Maps SDK on your iPhone app. One last thing though. I’d written this code and tested it on the simulator and everything was just dandy. I then tried compiling it on my iPhone and I got this error:

This was baffling because:

a. It compiled and ran perfectly on the iPhone Simulator

b. I don’t use NSURLIsExcludedFromBackupKey anywhere in my code and nor do any of the frameworks I use.

c. StackOverflow did not seem to have any answers regarding this. (for once!)

The iPhone (I use for testing) runs iOS 5 and I figured that was the problem. It is probably a compile time error because I’ve added a check that accesses the code only if the version of iOS is greater or equal than 5.1. Thus I added a small hack to bypass this limitation, in the ViewController in which I was referencing the Google Maps SDK.

In my .h file I added a const NSString like so

[sourcecode language=”objc”]

#import <GoogleMaps/GoogleMaps.h>

extern NSString* const NSURLIsExcludedFromBackupKey;

@interface MapViewController : UIViewController  {

}

[/sourcecode]

And in my .m file I added this:

 

[sourcecode language=”objc”]
@implementation CreateRequestViewController

NSString* const NSURLIsExcludedFromBackupKey = @"NSURLIsExcludedFromBackupKey";

– (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {

}

[/sourcecode]

Don’t forget to add the open-source attribution aspart of a legal notices section in either your ‘About’ or ‘Help’ page. Just call [GMSServices openSourceLicenseInfo] which returns a NSString which currently reads “This software is based in part on zlib: Copyright 1995-2012 Jean-loup Gailly and Mark Adler”. This just in case you need to format your UILabel.

Hope this blog post made it easier for you to add Google Maps to your awesome app.