Foursquare Client

The original idea for this lab was to upgrade our Twitter Client from Class 5 with map capabilities but unfortunately, Twitter decided to completely change and complicate their API so we’ll need to get some data from somewhere else.

So for this lab, you’ll be building a Foursquare Client for displaying restaurants nearby on a map.

You can start from scratch if you’d like, but you can also continue where you left off with your Twitter Client, or you can download my starter project. All I’ve done is change the request to point to Foursquare, and populated the table view with the response data.

You’ll also notice that the request URL includes a client ID and client secret. That’s because the Foursquare API requires you to authenticate to use it. You can create your own “app ID” here, or you can just use the one from my starter project.


  • You must use Core Location to determine your latitude and longitude.
  • You must edit the URL string to put in your coordinates for the ll variable, replacing 40.7 and -74.
  • You must customize your map annotation views.
  • Your detail view controller needs to provide more information than the map view, and should look nice. In other words, do something more original than what I did in the above screenshot.


Displaying Maps

The Map Kit framework provides a set of classes for embedding maps into your apps.

Map Kit does not include any location sensing functionality, and so it is often used in conjunction with the Core Location framework.

Map Kit is not included by default in a new Xcode project. You need to make sure to properly link to the MapKit.framework in the Build Phases tab of your project settings if you want to use any classes starting with the MK prefix.

Displaying Maps

MKMapView is used to add a map view to your app. MKMapView extends UIView, so it inherits all of its properties. The easiest way to display a map view is to drag it to your main view in the Storyboard.

The map view has standard display type by default, but it can also have a satellite or hybrid type. This can be set in the Storyboard or using the mapType property.

By default, the map view zooms, scrolls, and does not display the user location. All these options can be edited in the Storyboard or by editing the zoomEnabled, scrollEnabled, and showsUserLocation properties respectively.

The region displayed by the map can be set and animated using setRegion:animated: method. The region is of MKCoordinateRegion type, which is a struct holding a CLLocationCoordinate2D for the center, and an MKCoordinateSpan for the span, which is itself a struct holding latitudeDelta and longitudeDelta, both of type CLLocationDegrees. An MKCoordinateRegion can easily be built using the MKCoordinateRegionMakeWithDistance(...) function.

Header Source


Map views can display hotspots in their view, which are called annotations. Any type of object can be used as an annotation, as long as it conforms to the MKAnnotation protocol. An MKAnnotation needs a coordinate, and can optionally have a title and a subtitle.

Header Source

Annotations can then be added to the map view using addAnnotation: or addAnnotations:.

Annotations can be removed from the map view using removeAnnotation: or removeAnnotations:.

Annotation Views

Annotations are drawn on the map view using an MKAnnotationView subclass. The default is the MKPinAnnotationView.

MKAnnotationView instances are created and assigned to an MKAnnotation in a way that is very similar to how UITableViewCell instances are created in a UITableView, using a reuse pool.

You can conform to the MKMapViewDelegate protocol and implement mapView:viewForAnnotation: to customize the annotation view.

mapView:didSelectAnnotationView: is called whenever an annotation view on the map is tapped.

If you also want the callout (info box with the title and subtitle) to appear on tap, you need to explicitly set canShowCallout to YES on the corresponding MKAnnotationView.

You can customize the callout by adding accessory views on the left and right using the leftCalloutAccessoryView and rightCalloutAccessoryView properties respectively. These can be set to any subclass of UIView. If they are set to a UIControl, mapView:annotationView:calloutAccessoryControlTapped: will be called on the delegate when they are tapped.

There are many more options for customizing MKAnnotationView. You can even completely replace the pin image by setting its image property.

  1. Paul Hegarty. Lecture 11 Slides. iPad and iPhone Application Development. Stanford, Nov 28 2011.

Sensing Location

Location sensing is achieved using the Core Location framework. The framework determines the position and heading using the hardware available on the device. This can include a GPS chip, a Wi-Fi antenna, a gyroscope, and an accelerometer. This hardware layer is abstracted from us and we are simply given the location with an accuracy level.

Core Location has no user interface, so it is up to you to represent the retrieved data in a meaningful way to your application.

Core Location is not included by default in a new Xcode project. You need to make sure to properly link to the CoreLocation.framework in the Build Phases tab of your project settings if you want to use any classes starting with the CL prefix.

Location Data

The basic location data object is CLLocation.

CLLocation incorporates the geographical coordinates and altitude of the device’s location along with values indicating the accuracy of the measurements and when those measurements were made. It also includes information about the speed and heading in which the device is moving.

The coordinate property is a struct holding a latitude and a longitude. Both are of type CLLocationDegrees, which is just a double. The value is given in degrees.

The accuracy of the measurement can be read using the horizontalAccuracy property, of type CLLocationAccuracy, which is just a double. The value is given in meters.

The altitude property holds the altitude value. Its accuracy can be read using the verticalAccuracy property. The value is given in meters. A negative value means below sea level.

The course property indicates the direction in which the device is moving, of type CLLocationDirection, which is also just a double. The value is given in degrees, with North at 0 going clockwise (East is 90 degrees). If the value is negative, it means the direction is invalid.

The speed property indicates the speed at which the device is moving in its current direction. It is of type CLLocationSpeed, which is a double, and the value is given in meters per second. If the value is negative, it means the speed is invalid.

Finally, the timestamp indicates the time at which all these values were determined. It is of type NSDate.

CLLocation also includes the distanceFromLocation: method, which returns the distance between it and another location. The value is of type CLLocationDistance, which is a double, and is given in meters.

Location Manager

You will usually not build your own CLLocation objects, but retrieve them from a CLLocationManager.

You can access properties directly from the location manager, but it’s usually a better idea to use delegation. Instead of polling the CLLocationManager constantly, we can conform to the CLLocationManagerDelegate protocol and have it notify us when new data is ready.

The first step is to check if the user has enabled location monitoring for their device.

You can then create an instance of the location manager, and tell it to begin sensing for location.

The first time your app requests to use location services, a pop up will appear asking the user to do so. You can add a little explanation to this by setting the purpose property.

Using the device’s location sensors is one of the biggest battery draining operation you can do. It’s a good idea to only turn on location sensing when the view is visible.

You can set the desiredAccuracy property as low as you need it to be to save power. Possible values are:

  • kCLLocationAccuracyBestForNavigation
  • kCLLocationAccuracyBest
  • kCLLocationAccuracyNearestTenMeters
  • kCLLocationAccuracyHundredMeters
  • kCLLocationAccuracyKilometer
  • kCLLocationAccuracyThreeKilometers

Once this is set, the device does its best using:

  • Cellular tower triangulation – not very accurate, but uses minimum power
  • Wi-Fi node database lookup – more accurate and requires more power
  • GPS – very accurate, but requires lots of power

The distanceFilter property can be set to only trigger events once there is a minimum change in position. The value is set in meters.

Once the manager is set up, we can get the location using delegate methods.

  1. Core Location Framework Reference. Apple, Oct 12 2011.
  2. Paul Hegarty. Lecture 11 Slides. iPad and iPhone Application Development. Stanford, Nov 28 2011.

Memory Management

Memory management is the act of managing computer memory. The basic idea behind this is to:

  1. Dynamically provide memory to an application when it is requested.
  2. Reserve that memory allocation while it is still in use.
  3. Free the memory when it is no longer needed, so that it can be reused.
1. is fairly straightforward. In fact, this is what you have been doing in your applications whenever you called alloc.

2. and 3. are the trickier aspects, and are notoriously a pain in most languages where memory management is performed manually.

Consider the following example.

We have two pointers to the same object, aView and theSameView.

Using memory management, we can deallocate the object.

This makes both pointers invalid, and the above app will crash when trying to use theSameView.

We can set the theSameView pointer to nil, but the app will still crash when trying to use aView, as that pointer is now referencing an invalid location.

At this point, you might be thinking that a good solution would be to never deallocate any objects. Unfortunately, that is a bad idea because there is a limit to the amount of total memory an app can use, and your app will crash if you ever reach it. Using up all available memory will also probably slow down your machine to a point where it’s unusable.

Reference Counting

How do you know when you’re done with your object? How do you know that your pointer is referencing an object that is still allocated?

One of the techniques is to use reference counting. This implies counting the number of pointers to an object in memory. Every time a pointer is added the counter increments. Every time a pointer is set to nil, the counter decrements. When the counter hits 0, it means that no pointers are referencing the object, and it can be safely deallocated.

As you can imagine, this process can get very tedious but luckily, many programming languages and compilers automate it.

The retain method increments the reference count, and release decrements it. In the above example, the object does not get deallocated when release is called on aView, because it still has a reference count of 1.

Automatic Reference Counting (ARC)

Before iOS 5, memory management had to be performed manually, but Automatic Reference Counting has been introduced in the later versions of the SDK.

This is an option that is set at the project level, and you’ve probably been using it for all the apps that you’ve built so far in the class.

ARC takes care of releasing and deallocating all the objects in memory that are not in use anymore. You simply need to set your pointers to nil when you’re done with them, and let the reference counter do its thing. You never need to call retain or release.

You can set the aView pointer to nil, but the theSameView pointer is still valid, as the object it points to still exists.

If you set both pointers to nil, then the reference count goes to 0 and the object is deallocated automatically.

Strong vs. Weak References

Modify the above example to use properties for your pointers.

This keeps the object in memory, as expected. What happens if we switch the reference type of theSameView to weak?

It’s not as bad as a crash, but the object referenced by theSameView has been deallocated, and theSameView now points to nil.

This happens because weak pointers are not counted by the reference counter. This is similar to using retain for strong pointers.

There are a few reasons why you would need weak pointers. Imagine you have a parent-child relationship between two classes where the parent has a pointer to its child and the child has a pointer to its parent. If you release the parent, you won’t be able to access it or its children anymore as you won’t have a pointer to reference it, but it will remain in memory because its children each have a pointer to their parent. This is called a retain cycle, and it can be avoided by using weak pointers from the children to their parent.

The general rule is that you want to use strong pointers to objects that you own, and weak pointers to objects that you borrow. This is why references to delegates tend to be weak, you’re just referencing those objects temporarily. Similarly for Storyboard outlets, which tend to be owned by their parent view, or by the base UIViewController class.

What about assign?

The assign directive is similar to weak except that it will not set the pointer value to nil when the referenced object is deallocated. It is conventionally not used for pointers, but for primitives (int, float, BOOL, etc.).

  1. Matthijs Hollemans. Beginning ARC in iOS 5 Tutorial Part 1., Nov 7 2011.

  2. Memory management. Wikipedia, Sep 25 2012.

  3. Reference counting. Wikipedia, Sep 1 2012.

Lateral Navigation

Lateral navigation implies replacing the current “mode” by an entirely different one. This is different from hierarchical navigation where you can access the history of views you had gone through, and from modal navigation which is a temporary takeover that eventually brings you back where you left off.

Tab Bar Controller

In iOS, lateral navigation is usually performed using a UITabBarController. The tab bar interface displays tabs at the bottom of the window for selecting between the different modes and for displaying the views for that mode. Each tab is associated with a custom view controller. When the user selects a specific tab, the tab bar controller displays the root view of the corresponding view controller, replacing any previous views.

The UITabBarController is usually at the root of the view hierarchy. The easiest way to create a tabbed application is to use the template provided by Xcode.

This will set a UITabBarController as the initial view controller, and add two lateral view controllers for you to start with. To add another tab, you can add a UIViewController to the Storyboard and drag a reference outlet from it to the viewControllers property of the tab bar controller.

You can then set up your view controller as you would regularly. The corresponding view will load the first time it is displayed, calling the viewDidLoad method, and stay loaded unless forced to unload. viewWillAppear: will be called every time the tab is selected, and viewWillDisappear: will be called every time the tab is deselected.

Tab Bar Items

Each view controller has a UITabBarItem associated to it, which can have a title, an icon, and a badge. The badge is text displayed in the top-right corner of the item, with a red oval around it. It is set using the badgeValue property.

You can use one of the built-in item styles provided by Apple (like Favorites, Contacts, History, etc.), which will automatically set the title and icon for you. You cannot edit either of these, but can provide a badge. Also note that if you use any of these built-in items, the mode associated with the tab must be somewhat related to the item, or else there is a chance that your app will be rejected for distribution by Apple.

Alternatively, you can provide your own icons and titles. The icon images must measure 30 x 30 pixels in standard resolution, and 60 x 60 pixels for Retina display. Only the alpha channel of the provided image is used to render the icon, so you should design a simple shape on a transparent background, stripped of any colour. The icon is automatically tinted by the tab bar controller to indicate selection.

The More Navigation Controller

The tab bar has limited space and can only display up to 5 items. If you add six or more view controllers to a UITabBarController, the tab bar will only display the first four items plus the standard More item on the right. Tapping the More item automatically brings up a standard interface for selecting the remaining items.

The interface for the standard More item includes an Edit button that allows the user to reconfigure the tab bar. By default, the user is allowed to rearrange all items on the tab bar. If you want some items to remain in place, you can remove their corresponding view controllers from the customizableViewControllers array property.

Combining Navigation Types

You’ll often want to use a UINavigationController inside a tab bar controller. This is done similarly to using a UIViewController; simply drag a reference outlet from it to the viewControllers property of the tab bar controller.

  1. View Controller Programming Guide for iOS. Apple, Sep 19 2012.