Fundamental Storyboarding: Pass Data Forward

This is the final workshop in the Fundamental Storyboarding series and it you will learn how to pass data forward to a destination view controller. You do this by creating a segue in Interface Builder then define the Storyboard prepareForSegue:sender:sender: method in your source view controller’s implementation file.

Passing Data forward to a Destination View Controller

To pass data forward to a destination view control, you’ll have to create a segue. A segue involves a source view controller and a destination view controller. The source view controller is the controller from which data is being passed and the destination view controller is the controller that is receiving the data. Before the segue occur, a prepareForeSegue:sender: method is fired. You put code in that method to pass the source view controller’s data to the destination view controller. A segue can be used to navigate forward through a push, modal or custom segue.

The key steps in performing a segue are as follows:

1. Give each segue a unique identifier. Since you’ll have more than one segue in the view controllers, you must give them a unique identifier. Your application use it to distinguish one segue from another. Take a look at Figure 1-1 below, it shows the direction of a segue and the syntax of the Storyboard’s prepareForSegue method.

fstoryboarding-fig20b
Figure 1-1: Segue direction and the syntax of the prepareForSegue method

2. Make sure both view controllers objects’ data types are the same. For example; say the destination view controller’s scene contains a Text Field control and it is connected to an IBOutlet property called talkShowHost. You want to display the name, Chris Hardwick in it. Well, in the source view controller, you’ll have to pass that name as an NSString object to the destination view controller’s Text Field control like this:

destinationViewController.talkShowHost = @”Patrick Ludwig”;

The text string on the right side of the equal sign is the source view controller’s object and its data type is of NSString. The object on the left side of the equal sign is the destination view controller’s object, called talkShowHost and its data type is of NSString. Since both view controllers objects’ data types are the same (an NSString), above statement will work; however, this statement:

destination.imageView.image = [UIImage imageNamed:@"apple.png"]

will cause the app to generate this cryptic error message in the Debugger window and image isn’t passed to the  destination view controller’s Image View control.

Invalid asset name supplied: (null), or invalid scale factor: 2.000000

Why is that you asked? Because the destination view controller’s object data type is of UIImageView; however, the source view controller’s object’s data type (located on the right side of the equal sign) is of UIImage. As you can see the controllers objects’ data types don’t match.

The Plan

The plan is to modify Scene 2 user interface to look like Figure 1-2. Define the Storyboard prepareForeSegue:sender: method in the source view controller’s implementation file (ViewController.m). Add code in it to pass an image of an apple to the destination view controller’s (SecondViewController) imageName property. Add code in the destination view controller’s ViewDidLoad method to load the image passed to its property, in Scene 2’s image view control.

fstoryboarding-fig24b
Figure 1-2: Image passed to the second view control

Add an Image in The Project

Ok, you know what the plan is, so let’s get cracking to implement it. The very first thing you have to do is launch the StoryboardFundamental project add an image in the project. So, drag-and-drop the image shown in Figure 1-3 in the project. Xcode respond by displaying the window shown in Figure 1-4 on your screen. Make sure you tick the Destination checkbox and the Folders radio button before clicking the Finish button. Xcode add the apple.png file in the project and it’ll show up in the Project Navigator pane.

apple fstoryboardin-fig22
Figure 1-3: Image to add in the project 1-4: File options window

Add an Image View on The Scene

What you need to do now is design the second scene to look like Figure 1-2 above, by adding a Text Field and an Image View control on Scene 2’s canvas. Don’t put any text the Text Field control.

Declare Properties in The SecondViewController Header File

Use Xcode’s Assistant editor to declare and connect an IBOutlet for the Image View control, in the SecondViewController.h file. While you are there, you should declare an NSString property called imageName in the file. When you are done, the SecondViewController.h file should look like this:

//
//  SecondViewController.h
//  StoryboardFundamental
//
//  Created by Merlyn on 10/10/13.
//  Copyright (c) 2013 The App Lady. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface SecondViewController : UIViewController

@property (strong, nonatomic) IBOutlet UITextField *textFieldMessage;

@property (strong, nonatomic) IBOutlet UIImageView *imageView;

@property (strong, nonatomic) NSString *imageName;

@end

Switch to the SecondViewController.m file and add highlighted statements in the viewDidLoad method.

- (void)viewDidLoad
{
  [super viewDidLoad];
  self.textFieldMessage.text = @"Storyboarding is cool!";
  self.imageView.image = [UIImage imageNamed:self.imageName];
}

Define The prepareForSegue Method

What you need to do now is add this code in the ViewController.m file, which define the prepareForSegue:sender: method.

// This method is fired prior to a segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
  if([segue.identifier isEqualToString:@"showScene2"]) {
    // Put the destination view controller in a variable
    SecondViewController *destination = segue.destinationViewController;

    // Pass the image name to the destination view controller's NSString property
    destination.imageName = @"orange.jpg";
  }
}

Code Analysis

The prepareForSegue:sender: method’s code is pretty straight forward, so I will just give you a heads up on the final statement that’s on line 09. As you can see that statement pass the image name to the destination view controller’s NSString object called imageName. At this point you’re are probably think this:

Why pass the image file’s name to string variable. Why don’t we simply initialize the Image View control in above method by replacing line 09 with this statement instead:

destination.imageView.image = [UIImage imageNamed:@”apple.png”];

The program will work; however, it will display this cryptic error message in the Debugger window and the image won’t show up in the second scene’s image view control. The reason for this is explained in above section, “Passing Data to The Destination View Controller”

CUICatalog: Invalid asset name supplied: (null), or invalid scale factor: 2.000000

You can view the objects stored in the prepareForSegue method’s parameters, sender and segue by using the NSLog() function in the prepareForeSegue: method like this:

Source Code
NSLog(@"The source view Controller: %@",segue.sourceViewController);
NSLog(@"The destination view controller: %@",segue.destinationViewController);
NSLog(@"Segue Name: %@",segue.identifier);
NSLo(@"The object that initiated the segue: %@",senders);

With that said, you can think of the imageName property as the middleman between the source view controller and the destination view controller. If you want to pass an image to the destination view controller, you’ll have to put it in the imageName property. The destination view controller’s viewDidLoad method takes care of loading the image in the Image View control, by executing this statement:

self.imageView.image = [UIImage imageNamed:self.imageName];

Set The Segue Identifier Attribute

The last thing you need to do now is, set the Identifier attribute fort the source view controller’s (ViewController) segue. Figure 1-5 shows you how to do it.

fstoryboarding-fig21
Figure 1-5: Set the segue Identifier attribute

Run The Application

That’s it, you are ready to see the fruit of your labor; so run the application and you will see output shown in Figure A below. Click the Goto Scene 2 button and you will see output shown in Figure B. As you can see code you entered in the prepareForeSegue:sender: method successfully pass the apple.png image name to the destination view controller (SecondViewController). Also, the destination view controller’s ViewDidLoad method is responsible for displaying data you see in the Text Field and the Image View control. Go ahead and click the second scene’s button to return to Scene 1. Figure C shows what it looks like now.

fstoryboarding-fig24a fstoryboarding-fig24b  fstoryboarding-fig24c
Figure A Figure B Figure C

That’s it, you’ve reached the end of the fourth workshop on Fundamental Storyboarding. The main goal of this workshop was to show you how to: pass data (an image) forward to a destination view controller. Until next time, happy coding! 🙂