Cross Platform
Android
iOS
Mac
Test Cloud

Introduction to Storyboards

A Storyboard is a visual representation of the appearance and flow of your application. Xamarin has introduced a Designer to allow Xamarin.iOS applications to take advantage of storyboards, so you can design your application screen visually and access the views, controllers and segues with C# for more control.

Overview

In this guide we will explain what a Storyboard is and examine some of the key components - such as Segues. We'll look at how Storyboards can be created and used, and what advantages they have for a developer.

Before the Storyboard file format was introduced by Apple as a visual representation of the UI of an iOS application, developers created XIB files for each view controller, and programmed the navigation between each view manually. Using a Storyboard lets the developer define both View Controllers and the navigation between them on a design surface and offers WYSIWYG editing of the application's user interface.

A Storyboard can be created, opened and edited with the Xamarin iOS Designer. This guide will also walkthrough how to use the Designer to create your Storyboards while using C# to programme the navigation.

Requirements

Storyboards can be used with the iOS Designer in Xamarin Studio 5.0 or higher, and with Xamarin 3 and above when using Visual Studio.

Storyboards

What is a Storyboard?

A Storyboard is the visual representation of all the screens in an application. It contains a sequences of Scenes, with each Scene representing a View Controller and its Views. These Views may contain objects and controls that will allow your user to interact with your application. This collection of Views and controls (or Subviews) are known as a Content View Hierarchy. Scenes are connected by Segue objects, which represent a transition between View Controllers. This is normally achieved by creating a Segue between an object on the initial view, and the connecting View. The relationships on the Design Surface are illustrated in the image below:

As shown, the Storyboard will lay out each of your scenes with content already rendered and illustrates the connections between them. It is worth noting at this point, that when we talk about scenes on an iPhone, it is safe to assume that one scene on the Storyboard is equal to one screen of Content on the device. However with an iPad it is possible to have multiple scenes appear at once, for example using a Popover View Controller.

There are many advantages of using Storyboards to create your application's UI, especially when using Xamarin. Firstly it is a visual representation of the UI, as all objects, including custom controls are rendered at design-time. This means that before building or deploying your application you can visualize its appearance and flow. Take the above image, for example. We can tell from a quick look at the Design surface how many Scenes there are, the layout of each View and how everything is related. This is what makes Storyboards so powerful.

Events are also much easier to manage with Storyboards, particularly when using the iOS Designer. Most UI controls will have a list of possible events in the Properties Pad, the event handler can be added here and completed in a partial method in the View Controllers class.

The content of a Storyboard is stored as an XML file. At build time, any .storyboard files are compiled into binary files known as nibs. At runtime, these nibs are initialized and instantiated to create new views.

Segues

A Segue, or Segue Object is used in iOS development to represent a transition between Scenes. To create a Segue, hold down the Ctrl key and click-drag from one Scene to another. As we drag our mouse, a blue connector appears, indicating where the Segue will lead as demonstrated in the image below:

On mouse-up, a menu will appear letting us choose the action for our Segue. It may look similar to the image below:

If you are using VMWare for your Windows Virtual Machine, note that by default Ctrl-click is mapped as the 'Right-Click' mouse button.

To create a Segue, edit your Keyboard preferences through Preferences > Keyboard & Mouse > Mouse Shortcuts and remap your Secondary button as illustrated below:

You should now be able to add a segue between your View Controllers as normal.

There are different types of transitions; each giving control over how the new View Controller is presented to the user and how it interacts with other View Controllers in the Storyboard. These are explained below. It is also possible to subclass a segue object to implement a custom transition.

  • Push - A push Segue adds the View Controller to the navigation stack. It assumes the View Controller originating the push is part of the same Navigation Controller as the View Controller that is being added to the stack. This does the same thing as pushViewController , and is generally used when there is some relation between the data on the screens. Using the Push Segue gives you the luxury of having a Navigation bar with a back button and title added to each View on the stack, allowing drill down navigation through the View Hierarchy.

  • Modal - A Modal Segue create a relationship between any two View Controllers in your Project, with the option of an animated transition being shown. The child View Controller will completely obscure the Parent View Controller when brought into view. Unlike a Push Segue, which adds a back button for us; when using a modal segue DismissViewController must be used in order to return to the previous View Controller.

  • Custom - Any custom Segue can be created as a subclass ofUIStoryboardSegue.
  • Unwind - An unwind Segue can be used to navigate back through a push or modal segue - for example by dismissing the modally-presented view controller. In addition to this, you can unwind through not only one, but a series of push and modal segues and go back multiple steps in your navigation hierarchy with a single unwind action. To understand how to use an unwind segue in the iOS, read the Creating Unwind Segues recipe.
  • Sourceless - A Sourceless Segue indicates the Scene containing the Initial View Controller and therefore which View the user will see first. It is represented by the Segue shown below:

Transferring Data with Segues

The benefits of a segue don't just end with transitions, they can also be used to manage the transfer of data between View Controllers. This is achieved by overriding the PrepareForSegue method on the Initial View Controller and handling the data ourselves. When the segue is triggered - for example, with a button press - the application will call this method, providing an opportunity to prepare the new view controller before any navigation occurs. The code below demonstrates this, from the Phoneword sample:

public override void PrepareForSegue (UIStoryboardSegue segue, 
NSObject sender)
{
    base.PrepareForSegue (segue, sender);

    var callHistoryContoller = segue.DestinationViewController 
                                  as CallHistoryController;

    if (callHistoryContoller != null) {
        callHistoryContoller.PhoneNumbers = PhoneNumbers;
    }
}

In this example, the PrepareForSegue method will be called when the Segue is triggered by the user. We first have to create an instance of the 'receiving' View Controller and set this as the segue's destination View Controller. This is done by the line of code below:

var callHistoryContoller = segue.DestinationViewController as CallHistoryController;

The method now has the ability to set properties on the DestinationViewController. In this example we have taken advantage of this by passing a list called PhoneNumbers to the CallHistoryController and assigning it to an object of the same name:

if (callHistoryContoller != null) {
        callHistoryContoller.PhoneNumbers = PhoneNumbers;
    }

Once the transition has finished, the user will see the CallHistoryController with the populated list.

Adding a Storyboard to a non-Storyboard Project

On occasion you may need to add a Storyboard to a previously non-storyboard file, doing this in Xamarin Studio has been made much more streamlined by following the steps below:

  • Add your Storyboard name to the Main Interface section of the Info.plist, as shown below: . This does the equivalent of instantiating the Initial View Controller in the FinishedLaunching method within the App Delegate. When this option is set in the Info.plist, the application instantiates your window (See below), loads the main storyboard and assigns an instance of your storyboard's Initial View Controller (the one beside the sourceless Segue) as the RootViewController property of your window and then makes the window visible on the screen.
  • In your AppDelegate, make sure to override the default Window method, with the following code to implement the window property:
    public override UIWindow Window {
          get;
          set;
        }

Creating a Storyboard with the Designer

A Storyboard can be created using the iOS Designer, which has been integrated seamlessly with Xamarin Studio and Visual Studio.

To get started using the iOS Designer to create storyboards, follow the Walkthrough - Using the iOS Designer. In this Walkthrough you will explore navigation between View Controllers using Segues, and how to handle events on your controls.

Instantiate Storyboards Manually

Storyboards totally replace individual XIB files in your project, however individual view controllers can still be instantiated using Storyboard.InstantiateViewController.

Sometimes applications have special requirements that can't be handled with the built-in storyboard transitions provided by the Designer. For example, if we were to create an application that launches different screens from the same button, depending on the current state of an application, we may want to instantiate the View Controllers manually, and program the transition ourselves.

The screenshot below shows two View Controllers on our Design Surface with no Segue between them. The next section will walk through how that transition can be set up in code.

  1. First, create a new empty iOS project. We'll call it Storyboard.Manual:

  2. Next, add an Empty iPhone Storyboard to the project. Call it MainStoryboard:

  3. Double click on MainStoryboard.storyboard to open it and add a new Navigation Controller to the design surface. As the Navigation Controller is UI-less, by default it will come with a Root View Controller, as illustrated below:

  4. Select the View Controller by clicking on the black bar at the bottom. In the Designers Property Pad, under Indentity we can specify a custom class as well as a unique ID for the View Controller. Set the class name and Storyboard ID to MainViewController.

    Later we will need to instantiate our View Controllers from the Storyboard and will use the Storyboard ID to reference it in our code. Setting the Restoration ID to match the Storyboard ID ensures that the View Controller gets recreated correctly if the state needs to be restored.

  5. We currently only have one View Controller, so drag another View Controller onto the Design Surface. In the Property Pad, under Identity set the class and Storyboard ID to PinkViewController, as illustrated below

    The IDE will create these custom classes for the View Controllers. These can be viewed in the Solution Pad, as illustrated in the screenshot below:

  6. In the PinkViewController, select the View by clicking towards the center of the controller's frame. In the Properties Pad, under View change the Background to Magenta:

  7. Finally, drag a button from the ToolBox onto the MainViewController. In the Properties Pad, give it the name PinkButton and the Title GoToPink, as illustrated below:

  8. Our storyboard is complete, but if we deploy the project now, we will get a blank screen. That's because we still need to tell the IDE to use our storyboard, and to set up a root view controller to serve as the first View. Normally this can be done through our Project Options, as shown above. However in this example we will achieved the same result in code, by adding the following to the AppDelegate:

    public partial class AppDelegate : UIApplicationDelegate
        {
            UIWindow window;
            public static UIStoryboard Storyboard = UIStoryboard.FromName ("MainStoryboard", null);
            public static UIViewController initialViewController;
    
            public override bool FinishedLaunching (UIApplication app, NSDictionary options)
            {
                window = new UIWindow (UIScreen.MainScreen.Bounds);
    
                initialViewController = Storyboard.InstantiateInitialViewController () as UIViewController;
    
                window.RootViewController = initialViewController;
                window.MakeKeyAndVisible ();
                return true;
            }
    
        }

    That's a lot of code, but only a few lines are unfamiliar. First, we register our storyboard with the AppDelegate by passing in the storyboard's name, MainStoryboard. Next, we tell the application to instantiate an initial view controller from the storyboard by calling InstantiateInitialViewController on our storyboard, and we set that view controller as our application's root view controller. This method determines the first screen that the user sees, and creates a new instance of that View Controller.

  9. Notice in the solution pane that the IDE has created a MainViewcontroller.cs class, and its corresponding designer.cs when we added the Class name to the Properties Pad in step 4. We can see this class created a special constructor that includes a base class:

    public MainViewController (IntPtr handle) : base (handle) 
    {
    }

    When creating a Storyboard using the Designer, the IDE will automatically add the [Register] attribute at the top of the designer.cs class, and pass in a string identifier, which is identical to the Storyboard ID specified in the previous step. This will link the C# to the relevant scene in the Storyboard

    Some instances may occur, where you want to add an existing class which was not created in the designer. In this case, you would Register this class as normal.

    [Register ("MainViewController")]
    public partial class MainViewController : UIViewController
    {
      public MainViewController (IntPtr handle) : base (handle) 
      {
      }
    
      ...
    }

    For more information on registering classes and methods, refer to the Type Registrar documentation.

  10. The last step in this class is to wire up the button and the transition to the pink View Controller. We'll instantiate the pinkViewController from the Storyboard; then, we will program a push segue with PushViewController, as illustrated by the example code below:

    public partial class MainViewController : UIViewController
      {
        UIViewController pinkViewController;
    
        public MainViewController (IntPtr handle) : base (handle)
        {
    
        }
    
        public override void AwakeFromNib ()
        {
          // Called when loaded from xib or storyboard.
    
          this.Initialize ();
        }
    
        public void Initialize(){
    
          var myStoryboard = AppDelegate.Storyboard;
          //Instatiating View Controller with Storyboard ID 'PinkViewController'
          pinkViewController = myStoryboard.InstantiateViewController ("PinkViewController") as PinkViewController;
        }
    
        public override void ViewDidLoad ()
        {
          base.ViewDidLoad ();
    
          //When we push the button, we will push the pinkViewController onto our current Navigation Stack
          PinkButton.TouchUpInside += (o, e) => {
            this.NavigationController.PushViewController (pinkViewController, true);
          };
        }
    
      }
  11. Running the application produces a 2-screen application:

Summary

This article introduces the concept of Storyboards and how they can be beneficial in the development of iOS applications. It discusses Scenes, View Controllers, Views and View hierarchies and how Scenes are linked together with different types of Segues. It also explores instantiating view controllers manually from a storyboard.