Introduction to iOS 5 Storyboards Part 2

Passing Data from One Screen to Another

This post continues from How To Use iOS 5 Storyboard Part 1 and uses the same project, StoryboardSample. Right now we have a two view controllers in our storyboard. When a user clicks on the button, the screen navigates to the second controller. Now we want to pass data from one scene to another using storyboards.

Passing Data From One Screen to Another

When a transition is happening from one scene to another, the storyboard runtime creates a segue object for that transition. A segue is an Objective-C object. It is an instance of class UIStoryboardSegue. A segue is represented in the Storyboard canvas.

When a transition happens, the current view controller will receive the prepareForSegue:sender: message where the prepareForSegue parameter will be an object of type UIStoryboardSegue. If you want to pass any data from the current view controller to view controller which is about to appear on the screen, you need to do that in the prepareForSegue:sender: method.

1. Add the following prepareForSegue:sender: method in the first view controller:

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    NSLog(@"Source Controller = %@", [segue sourceViewController]);
    NSLog(@"Destination Controller = %@", [segue destinationViewController]);
    NSLog(@"Segue Identifier = %@", [segue identifier]);

If you run this app now, you will see the results in the console window. However, the identifier variable is nil. Each segue has an identifier which can uniquely identify that segue.

Since one scene can have more than one segue associated with it, it is good to give your segues identifiers that you can then detect in your view controllers and take action accordingly.

A segue object in IB is the connection between two scenes as shown in Figure 1.

Segue arrow

Figure 1

Follow these steps to give your segue an identifier:

1. Select your segue object in IB
2. From the View menu, select Utilities->Show Attributes Inspector
3. In the Attributes Inspector, in the Identifier text field, write text for the identifier value for this segue. I named the identifier, SegueId1. Press Enter.

Also, add a second view controller to the project navigator. Follow the following steps to add a view controller to your existing project.

1, Go to File -> New -> New File. A New File dialog should appear as shown in Figure 2

Add New File dialog

Figure 2

2. Select Cocoa Touch under iOS on the left side and then select UIViewController subclass on the right.
3. Click Next and enter a Class name, I chose SecondViewController. Leave Targed for iPad and With XIB for user interface unchecked as shown in Figure 3

Name View Controller

Figure 3

4. Choose a folder to save new file and click Create button.

Your project navigator should contain similar files as shown in Figure 4

Project Navigator Files

Figure 4

You can see that when the storyboard runtime calls the prepareForSegue:sender: method in the current view controller to prepare it for the segue, the destination view controller has already been initialized in the segue object. Now this is your chance to pass any required data to the destination view controller, SecondViewController.

You can either set the data directly into a property of the destination view controller or pass your data by calling a method on that view controller. Below is the updated code to pass data from the first view controller to the second view controller. Add an import statement at the top of the implementation file of your first view controller to reference the second view controller as shown in Figure 5.

Import Statement

Figure 5

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    NSLog(@"Source Controller = %@", [segue sourceViewController]);
    NSLog(@"Destination Controller = %@", [segue destinationViewController]);
    NSLog(@"Segue Identifier = %@", [segue identifier]);

    if ([[segue identifier] isEqualToString:@"SimpleSegueToSecondViewController"])
        SecondViewController *viewController = [segue destinationViewController];
        //viewController.dataModel = ...

Adding a Storyboard to an Existing Project

If you already have an existing project where you navigate between screens manually and you want to start using storyboards, I will show how to take advantage of them with the below steps. The structure of project apps that use storyboards are different than project apps that do not. For once, the storyboard-based apps no longer use a main nib file for their windows. This needs to be removed from the .plist of our app. Also, when updating an old app to now use storyboards, you will need to make the app understand what storyboard files are by setting them in the .plist.

The last step below mentions to make sure that the app delegate in your app is not messing with how we are intending to load our storyboards. All apps are different, but you have to make sure that the app delegate is not assigning any object to the rootViewController property of the window. If it does, your storyboards will not be displayed and you will spend time trying to find out what the issue is.

1. From the File menu, choose New->New File
2. In the New File dialog, make sure you have selected User Interface under iOS on the left side and select Storyboard on the right.
3. Click Next to move to the next screen.
4. In this screen, pick the Device Family for which you want to create your storyboard. If your app is an iPhone or iPad only app, then pick the appropriate device family. If your app is a universal app, you will need to select one device family now, create the storyboard file and then come back and create another one for your other device family. Then press the Next button.
5. Now select where to save your storyboard file.
6. In the Project Navigator in Xcode, find the *Info.plist file. Note that this *.plist file might have been stored under a different name depending on the name of your project. Once you click on this file, the property list editor will open automatically as shown in Figure 6

Plist Editor

Figure 6

7. If you have any of the following keys, delete them from the *plist file: NSMainNibFile and NSMainNibFile~ipad
8. If you have an iPhone or iPad only app, then create a new key called UIMainStoryboardFile for iPHone or UIMainStoryboardFile~ipad for iPad. If you have a universal app, create both these keys.
9. For the value of these keys, provide the filename of the storyboards that you created without the .storyboard extension.
10. Make sure to save the .plist file.
11. Remove the application:didFinishLaunchingWithOptions: method from your app delegate’s implementation. Usually in this method, you write logic to set up different view controllers and windows and etc. With storyboards, you will no longer need this. At the very least, just remove the logic code in this method if you have any other code inside that remains relevant.

Understanding ViewControllers

Chapter 7 – View Controllers
To be honest, I quickly jumpted to Chapter 10, since that is the chapter to start working on the Homepwners application.  While only skimming through the previous chapters, I should of spent more time reading Chapter 7 on View Controllers.  So before I continue working on the next chapter on the Homepwners application, I would like to write a blog post on View Controllers.

Most iOS applications will need multiple “screens”.  In iOS development, each screen typically gets its own controller and XIB file.  Each controller has a view that gets placed on the winow.  Thus, we call these controllers, view controllers.  A view controller is a subclass of UIViewController and has an instance variable called, view.  And, we typically need an object to take care of the view swapping for us.  For this chapter, the example application will show the swapping is done by a UITabBarController. 

The iOS example application for this chapter contains two view controllers.  One displays the HypnosisView and the other will let the user get the current time by tapping a button.  The swapping of views uses the UITabBarController.

Now when creating views for the view controllers, there are two ways to do this: create the view programmatically or create a XIB file.  A good rule-of-thumb in deciding when to do one versus the other is if the view has no subviews, create it programmatically.  For Chapter 11 when we added a header control above the UITableView, we created a new viewcontroller and view.  If you remember, we created the view by creating a new XIB file made up of a UIView and 2 UIButtons, Edit and New.  We then made a action connection from each UIButton to the viewcontroller.  We then made a outlet connection from the FileOwner to the UIView control.  Then we load the XIB file manually using NSBundle in the viewcontroller by implementing headerView.  Reminder, XIB files are typically used to create the window and application delegate and to create the view for a view controller.

Chapter 7 helped me understand viewcontrollers much more in depth.  Stay tune for more implementation on the Homepwner class.