Using the Google Places API With MapKit
This is a post by iOS Tutorial Team Member Jason van Lint, the founder and owner of Dead Frog Studios, a boutique design and app building studio in Neuchatel, Switzerland. In the past, we wrote a tutorial on MapKit showing you how you can display your current location on the map and plot some information […] By .
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Using the Google Places API With MapKit
40 mins
This is a post by iOS Tutorial Team Member Jason van Lint, the founder and owner of Dead Frog Studios, a boutique design and app building studio in Neuchatel, Switzerland.
In the past, we wrote a tutorial on MapKit showing you how you can display your current location on the map and plot some information on it.
That’s a great start, but what if you want to show your users the locations of nearby locations like bars, restaurants, or cafes? It’s impractical for a small developer to build up a database like this yourself, so what do you do?
This is where the Google Places API comes to the rescue! This is a free web service API you can use to query to find establishment, geographic locations, or other points of interest near any given point, and you’ll get to try it out in this tutorial!
This tutorial assumes some familiarity with Objective C and iOS programming. You’ll be using Xcode 4.2 and such iOS5 features as Storyboards and ARC.
In addition, this tutorial assumes you have a working knowledge of JSON. If you are unfamiliar with JSON, you may want to check out this tutorial before you proceed.
Getting Started
To use Google Places, you use HTTP requests to query for places of a certain type, and Google Places will return search results as latitude/longitude coordinates.
Let’s say, for example, that you wanted to search for bars around a particular point on the map – perhaps your current location. You can send your local coordinates to the Google Places API asking it to search for places of type “bar,” and in return you’ll receive a list of places matching that search criteria. The places can then be added as “pins” on your application’s map interface.
Sound familiar? Yep, Google Places is an integral part of the Maps app that comes with the iPhone, and is also widely used by travel apps.
The API is, in fact, even more powerful that this brief introduction suggests. This tutorial, though, will focus only on how to send and receive information from the API, so you can use the map-plotting feature in your own app.
Ready to get started?
Fire up Xcode, go to File\New\Project, select iOS\Application\Single View Application, and click Next. Type GooglePlaces as the project name. Make sure the Use Storyboard and Use Automatic Reference Counting options are checked, click Next, and choose a place to save your project.
Click on MainStoryboard.storyboard to bring up Interface Builder. Bring up the Object library by selecting the third tab in the View toolbar (Utilities) and selecting the third tab in the library toolbar (Object library), as shown in the screenshot below.
From the Object library, drag a toolbar to the top of the screen, and a Map View to the middle of the screen. Rename the toolbar button “Bar,” as below:
The Bar button will serve as your trigger for the app to search for bars and plot them on the map. To show the features of the Google Places API, you’re going to need a few more place types. From the Objects library, drag four more Bar Button items onto the toolbar and name them “Café,” “Florist,” “ATM,” and “Park.”
Your interface should now look like this:
Adding the Required Frameworks
Before you can take what you’ve done for a test run, there are a couple of frameworks you need to make the map and user location-finder work. If these frameworks aren’t added, the app will crash before you even get a chance to click anything.
Click on the name of your project in the Project Navigator, select the GooglePlaces target, and switch to the Build Phases tab. Under the Link Binary With Libraries section, click the Plus button, find the entry for MapKit.framework, and click Add (+). Next, find the entry for CoreLocation.framework and click Add once again.
At this point your screen should look like the one below:
Compile and run, and you should have the beginnings of a working map. If you are using the iOS simulator, you should see a screen like this:
Wait, there’s something off about this map… where’s the little blue dot showing my current location? Where am I?!
Don’t get disoriented. There’s no blue dot because you haven’t set the property of the map view that enables it. You can always do this by ticking the “Shows User Location” box in the attributes pane for the map view. But for this tutorial, you’re going to set this property in code when you start up the application.
You are also zoomed out quite a bit and, ideally, you’d like to see your blue dot nicely framed in a 1-km area. It’s time to get your code on!
Zooming to Your Location
You need to import the two frameworks you added above because you are about to reference objects in your code that depend on them! Replace the contents of ViewController.h with this:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
@interface ViewController : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate>
@end
Now connect the Map View object you added to your interface to the view controller that was created for you when you started a new project in Xcode. To do this, select MainStoryboard.storyboard and click on the Assistant Editor icon seen below:
You should now see your storyboard alongside another window that most likely contains code. You need ViewController.h to appear in the code window. If it doesn’t appear automatically, make sure that the toolbar above the code window has Automatic selected, as seen here:
Hold down the Ctrl key and drag a line from the Map View to ViewController.h, between the @interface and @end.
A popup will appear. Set the connection type to Outlet and the name to mapView, keep the Type as MKMapView, and click Connect. This will make a property for you and automatically hook it up to Interface Builder. Your ViewController.h should look like this:
Note: The filled-in gray dot next to your @property statement tells you that it is connected to an object in Interface Builder. If this dot is not filled in, you have no connection with Interface Builder and probably need to reconnect it to something.
To double-check whether it is connected, you can always select the Map View object in your storyboard and click on the Outlets button in the inspector window. It should look like this:
Note: The filled-in gray dot next to your @property statement tells you that it is connected to an object in Interface Builder. If this dot is not filled in, you have no connection with Interface Builder and probably need to reconnect it to something.
To double-check whether it is connected, you can always select the Map View object in your storyboard and click on the Outlets button in the inspector window. It should look like this:
Now that your Map View object is connected to ViewController.h, you can start to interact with it and manipulate it via code.
The first thing you want to do is get your current location so that you can zoom into it. To do this, you’re going to make use of some standard functionality of the Core Location framework. The idea is to query your device for the current location, then send this location with a “zoom” factor to resize the map to a within a 1-km zone.
To begin, create an instance variable in the class that holds this information. Add this to ViewController.h above the @property statement:
{
CLLocationManager *locationManager;
}
The space between the curly braces contains the declarations for your instance variables. You declared a variable called locationManager that will hold information about your current location. It uses a special class from your Core Location framework.
Now switch to ViewController.m and replace viewDidLoad with:
-(void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//Make this controller the delegate for the map view.
self.mapView.delegate = self;
// Ensure that you can view your own location in the map view.
[self.mapView setShowsUserLocation:YES];
//Instantiate a location object.
locationManager = [[CLLocationManager alloc] init];
//Make this controller the delegate for the location manager.
[locationManager setDelegate:self];
//Set some parameters for the location object.
[locationManager setDistanceFilter:kCLDistanceFilterNone];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
}
Here, you set the delegate of the Map View object to self. You’ll use some delegate methods later, so you set this up now to make sure you won’t forget it. Then you set the Shows User Location property of the Map View. You instantiate the locationManager variable, and also set its delegate to self.
Finally, you set some basic parameters on the locationManager object that will ensure you get accurate results from the device, and that the distance is measured relative to the previously-delivered location. You use the value kCLDistanceFilterNone to be notified of all movements.
Build and run your app now. The first thing you’ll notice is that the simulator asks for your permission to use your current location.
This is the Core Location framework in action. It realizes that you are probably going to be asking for some location information from the device, so the first time it executes, it prompts the user to see whether this is all right:
Click OK and you will notice that, finally, your blue dot appears. But still no zoom. You’ll implement that now.
Add the following method at the bottom of ViewController.m (but above the final @end):
#pragma mark - MKMapViewDelegate methods.
- (void)mapView:(MKMapView *)mv didAddAnnotationViews:(NSArray *)views {
MKCoordinateRegion region;
region = MKCoordinateRegionMakeWithDistance(locationManager.location.coordinate,1000,1000);
[mv setRegion:region animated:YES];
}
You are using a delegate method of the mapView class that gets called every time an “annotation” or pin is added to the map. In this case, the blue location dot is also considered an annotation, so this gets called as soon as your location dot is added to the map.
You declare a variable that will hold the coordinates of the region you want to display on the map. Then you call the handy setRegion method provided by your MapKit framework. setRegion centers the visible area of the map on your position with a 1000-m x 1000-m area around it. How nice of it to do the work for you. :]
Build and run your app, and you should zoom in nicely on your current location.