Localization is the process of making your apps work with multiple languages.

This is surprisingly a lot simpler than it sounds, and is achieved by calling special functions and through built-in Xcode support.

Download the starter project to begin.

Localizing Strings

The first step in localizing an app is to separate all the text from the code. We will move all hard-coded strings to a special .strings file. You should name this file Localizable.strings so that your app knows where to look for it. Otherwise, you’ll have to add an entry to your .plist file.

The format for each entry in the file is "Key" = "Value";.

You can then read and use this data in your app using the NSLocalizedString macro.

You can now localize this file for the English language.

  1. Select the Localizable.strings file from the Project Navigator (on the left).
  2. Click on the Make localized… button in the File Inspector (on the right).
  3. Select English as the initial localization from the menu that pops up.

Repeat the process for the hello.jpg file.

If you examine the project files in the Finder, you will notice that both files have been moved inside a folder called en.lproj. You can localize your app in 40 languages, each identified with a 2-letter code.

You can add a French localization to the app from the project’s Info tab.

Xcode will ask you which files to include in the new localization. Select all but the Storyboard.

This will copy the selected files into an fr.lproj folder.

Rename allo.jpg to hello.jpg, and replace the version in fr.lproj.

Back in Xcode, you will notice that you can now edit two versions of the localized files. Replace the contents of Localizable.strings by their French counterparts.

You can now run your app on a French language device, and it will automatically load the correct text and resources.

You can also localize the app name by adding an entry for the CFBundleDisplayName key of the InfoPlist.strings file.

Note that sometimes changes won’t load while testing because of caching issues. Make sure to delete the app from the Simulator and to clean the project in Xcode if you encounter any refresh problems.

Design Briefs

In today’s lab you are going to team up with another student in the class and come up with solutions to design briefs. You will then present your results to the rest of the class and we will discuss the pros and cons of your solutions.

Keep in mind the App Design Guidelines when thinking about these problems.

  1. Design a control interface for a 2D platformer game for the iPhone.
    • You need controls for moving to the left and to the right, and for controlled jumping, i.e. the user needs to be able to perform short and long jumps.
    • Because of the limited space on the iPhone screen, you can’t use a directional pad.
  2. Design the complete experience and interface for a video kiosk app for iPad.
    • The app is intended for a museum setting, as a guestbook for patrons to leave comments at the end of their visit.
    • The app must record a short video using the camera and submit this video to the museum’s YouTube account. It can provide any features you feel are necessary to perform this main task.
    • Include all the screens you design and the flow from screen to screen in your solution.
  3. Design the control interface for a Tetris game for the iPhone.
    • You need controls for moving the falling piece to the left and to the right.
    • You need controls for rotating the falling piece clockwise and counterclockwise.
    • You need controls for dropping the falling piece instantly onto the game floor.

Scrolling Forms

Sometimes, you will need to build forms to capture a lot of information from your user. Download and run the following starter project.

If you don’t put too much thought into this, it can be a real pain for your user. Let’s look at ways to make this process as easy as possible.

Customizing the keyboard

The first thing to do would be to set the right keyboard type for each field. In the above example, most fields will just use the Default keyboard, but you should set the email field to use the E-mail Address keyboard, and the phone number field to use the Numbers and Punctuation keyboard. This will prevent the user from manually having to switch keyboards when inputting that data.

Another easy improvement is to set an appropriate title for the Return key. In our case, it should be Next for all fields but the last one, where it should be Done.

Auto-selecting the next field

The next improvement would be to hide the keyboard when the Return key is pressed. In your past apps, you probably did this by calling resignFirstResponder on your UITextField instances, either as a callback from the delegate or from the Did End On Exit event.

In this case however, it would be better to automatically select the next field until we reach the last one, where we would finally hide the keyboard.

First, set your view controller to conform to the UITextFieldDelegate protocol.

Then, set the delegate of each text field to your view controller.

Then, set the tag of each text field to an incrementing value starting at 1. We start at 1 because the default is 0, and we want to filter out all other UIViews on screen. In this example, the first name text field will have tag 1, the last name will have tag 2, and so on until the phone number at tag 9.

Once that’s done, you can implement textFieldShouldReturn:, which will get called every time the Return key is pressed.

The code will read the tag of the field that just returned. If it’s the last one, it will hide the keyboard, otherwise it will automatically focus on the next field.

You can go one step further and automatically populate the list of entry fields. That way, you can add or remove fields without having to worry about the value of the last tag.

Scrolling the fields into view

You’ve probably noticed by now that all the fields in the bottom half of the screen are hidden by the keyboard. This is really bad for the user experience because you can’t tell if you’re in the right field or even if you’re entering any data at all.

The solution to this problem is to put all the fields in a scroll view, and to have it automatically scroll so that the field in focus is always visible.

The first thing you need to do is to calculate how much space the keyboard takes up. You can do this by listening for notifications on when the keyboard will show, and to measure its size when it is on screen.

You can then move all the text fields inside of a UIScrollView, and create an outlet for this scroll view in your view controller.

Header Source

You can then add a method that will scroll to position a subview in the middle of the available space on screen, and call that method every time a new text field is selected.

At first glance, this seems to work fine, but if you play with it a bit you’ll notice that the centering code does not work the first time it is called. That’s because textFieldDidBeginEditing: is called before keyboardWillShow:, and so the _keyboardBounds are not set the first time scrollViewToCenterOfScreen: is called.

You can fix this by saving a reference to the text field that is being edited, and calling scrollViewToCenterOfScreen: directly from keyboardWillShow:.

Finally, you’ll want to add a method to scroll the view back down to its original position, and call that method whenever the keyboard will hide.

You might notice that the view doesn’t actually animate down, but jumps down directly. That’s because of the call to setContentSize:, which sets the content to fit into the app frame, so there’s nowhere left for it to scroll. This can be fixed by “manually” animating the offset.

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.


Testing Apps on a Device

Although testing your apps in the iOS Simulator is a good first step, you must make sure they also run properly on an actual device. There are a few differences between running an app on the simulator and on a device that you should be aware of:

  • The processor speed is different. Apps tend to run faster in the simulator.
  • The memory capacity is different. You’ll need to manage your memory more efficiently on a device if you want to avoid out-of-memory errors.
  • You can accurately test multitouch input.
  • You can use the camera to grab images and video.
  • You can use specific inputs not available in the simulator, such as audio, location, orientation, proximity, etc.
  • You can test network connections in a real world setting. This is particularly important if your app needs to connect over the cellular network.


Unfortunately, installing apps on an iOS device is a convoluted process. Later versions of Xcode simplify the process a little, but you should still be aware of what all the pieces of the puzzle are in order to properly troubleshoot any issues.

Key A digital identity, consisting of a secret private key and a shared public key. This private key allows Xcode to sign your iOS application binary.
Certificate An electronic document that associate your digital identity with other information, including your name, email address, or business. All iOS applications must be signed by a valid certificate before they can be run on an Apple device.
Device An Apple device that is authorized to run developed applications. The device is identified by a Unique Device Identifier (UDID).
App ID A unique identifier that iOS uses to identify your application, connect to the Apple Push Notification service, share keychain data between applications, and communicate with external hardware accessories you wish to pair your iOS application with. You can create a wildcard App ID if you want a suite of applications to share data. 

Each App ID consists of a unique 10 character Bundle Seed ID provided by Apple and a Bundle Identifier suffix that is provided by the developer. An example App ID would be 8E549T7128.net.silentlycrashing.cart498j.FeedTheCat

Provisioning Profile A collection of digital assets that ties it all together, containing a set of iOS Development Certificates, Unique Device Identifiers and an App ID. The Provisioning Profile must be installed on each device on which you wish to run your application code.


You must be registered as an Apple Developer and subscribe to the iOS Developer Program. There are many flavours of developer programs, with yearly fees ranging from $0 to $299. depending on the size of the team and the type of distribution required.

Team Members can have many different roles:

Agent The primary contact for the development team. The Agent is responsible for accepting agreements and can enroll their team in additional Apple Developer Programs. The Agent is also the only member that can submit an app for review to Apple.
Admin Admins can invite members, approve Certificate signing requests, register App IDs and Device IDs, and create Provisioning Profiles.
Member Members can submit Certificate signing requests, and download Provisioning Profiles.

Our Team

Our class is registered to the University Program, which allows us to develop apps for educational purposes at no cost, but does not allow any distribution.

I am the Team Agent, and have generated a Certificate using my Key as identification. I registered a wildcard App ID for use in the class, and have generated a Provisioning Profile linking the Certificate to the App ID.

You will all be Team Members.

  1. Register an account as an Apple Developer.
  2. Accept my invitation as a Member of Concordia University (Design and Computation Arts).

You will e-mail me your Device IDs and I will add them to the list of authorized devices on our account.

  1. Locate your Device UDID.
  2. E-mail it to me along with the device model you own, for example: iPhone 3GS.

Once I have added all the devices, I will add them to the Provisioning Profile. To keep things simple, we will all share the Certificate and Provisioning Profile I will generate.

  1. Download and double-click the archived Key and Certificate. This will add the right entries to your Keychain. I will give you the required password in class.
  1. Download and double-click the archived Provisioning Profile (link coming soon). This will add the Profile to Xcode and automatically upload it to your phone when plugged in.

If you’re doing this on one of the computers in the lab, you will have to re-download both archives every time you log in as the machines are wiped out daily.

Running on a Device

  1. Open one of your projects in Xcode.
  2. Plug your iOS device in the computer.
  3. Select the device from the scheme menu at the top.

  1. Make sure the correct profile is selected in the Code Signing section of the Build Settings.

  1. Build and run your app.


Twitter Client

We are going to build a simple Twitter client for displaying the public timeline. We will be using AFNetworking to retrieve our date from the net, and a UITableView to display this data in our app.


Let’s start by making a request to the Twitter API and seeing what the response looks like.

If we pull out one entry from the response, we can find the relevant fields for our application.

Let’s build our own dictionary of tweets, stripping out all the data we don’t need.

We can now use our clean dictionary to populate our table view. We’ll set tweet as the main cell text and the user name as the detail text.

AFNetworking also includes a category (more on categories later) for UIImage which adds functionality to load a remote image.

As a final exercise, add a detail view controller to your app that is displayed when a cell is selected. The view should at least contain the tweet and user image of the corresponding cell, and you can also add more information to it if you’d like.

I will provide my sample application at the end of class.


Image Sequences

You have already used UIImageView to display an image, but it can also be used for displaying image sequences.

Header Source

View Animations

Most UIView properties can be animated, using class methods and blocks.

Let’s prepare an app for testing animations. First, create a custom UIView for drawing a target.

Header Source

Next, add this view to the center of your main view.

Next, add a gesture recognizer for double-tapping the main view.

You can now animate the target to the touch point using animateWithDuration:animations:

You can animate multiple views at the same time.

And you can add a completion handler, called when the animation is finished.

You can even nest other animations in the completion handler.

You can add a starting delay and set the easing function to your animation, using animateWithDuration:delay:options:animations:completion:

There are many different animation options. You combine them using the pipe | operator.

View Hierarchy Animations

You can animate transitions between views using transitionFromView:toView:duration:options:completion:

Smiley App

Build an app with a custom UIView that draws a smiley face.

  • You can only use Core Graphics methods for drawing.
  • The face must scale properly depending on the size of the view.
  • The face does not need to be identical to the example, but you should use this exercise to explore the many different options offered by the Core Graphics framework.

If you finish before the end of class, add some animation to your smiley face.

Here is my version.



Scroll Views

Scroll views are used when content that needs to be displayed won’t fit in its entirety on the screen. The UIScrollView class provides functionality to:

  • Scroll through content that is bigger than the size of the view, using pan gestures.
  • Zoom in and out of content, using pinch gestures.


Scrolling is fairly straightforward, no special delegation or gesture recognizers are required. The UIScrollView simply scrolls its subviews.

  1. Add a UIScrollView to the display.
  2. Build some subviews, setting their frame property to position them in the scroll view.
  3. Set the scroll view’s contentSize property to a value great enough to cover all the subviews. contentSize does not get set automatically and defaults to CGSizeZero, so don’t forget this step!
Header Source

Steps 1 and 2 can be performed in the Interface Builder as well, but step 3 must be done in code.

We can retrieve the content offset using the bounds or contentOffset properties.

We can update our ViewController to conform to the UIScrollViewDelegate protocol, and read out the content offset whenever it changes by implementing - (void)scrollViewDidScroll:(UIScrollView *)scrollView.

Header Source


Zooming requires a couple of extra steps.

  1. Set the scroll view’s minimumZoomScale and maximumZoomScale properties.
  2. Register a delegate on the UIScrollView which implements - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView.

That’s all it takes to zoom using the pinch gesture. If you need to support additional gestures (for example, double-tap to zoom all the way out), you will need to add the corresponding UIGestureRecognizer on the scroll view.

Manually Scrolling and Zooming

As a final exercise, let’s programmatically add a couple of UIButtons to the view for saving and restoring the current scroll offset and zoom scale.