Cross Platform
Android
iOS
Mac

Introduction to Storyboards

Apple introduced a new method for designing user interfaces in Xcode 4.2 and iOS 5 called Storyboards. A Storyboard defines both the view controllers and the navigation mechanism between them (called a ‘segue’). Xamarin Studio integrates with Xcode to allow Xamarin.iOS applications to take advantage of storyboards, so you can design your application screen and workflow Storyboard in Interface Builder and then access the views, controllers and segues with C#.

Overview

Storyboards are a new way to build application user interfaces in Xcode. Developers previously created XIB files for each view controller, and programmed the navigation between each view manually. A Storyboard defines both view controllers and the navigation between them on a design surface that offers WYSIWYG editing of the application user interface.

This article provides step-by-step instructions for creating a simple screen navigation flow using a Storyboard with Xamarin.iOS. Then, we delve into working with storyboards programmatically.

Note: This example is for Xamarin Studio only, as Xamarin.iOS for Visual Studio does not currently support Interface Builder integration and Storyboards.

Requirements

This guide assumes the latest XCode from Apple, and the latest Xamarin Studio and Xamarin.iOS.

Creating a Storyboard App

Xamarin Studio includes Xamarin.iOS templates to create new iOS applications using a Storyboard, as shown in the New Solution dialog.

The code for this example is available in the Storyboard.zip file.

The starting point is choosing a new iPhone Storyboard: Utility Application that loads in Xamarin Studio like this:

Double-click the Storyboard file to open Xcode. It will show the two View Controllers that are pre-defined by the template. If you return to Xamarin Studio and run this application, the info button will already work: flipping to the second view controller.

To add new elements to the Storyboard you need to use the Object Library. Press the right-most View button in the top-right corner of Xcode to show the left pane. Show the Object Library by pressing the ‘cube’ in the bottom pane, then find the Navigation Controller (yellow circle with a black button inside) and drag it onto the design surface as shown:

Now you need to create a ‘segue’ (as Apple calls them) to the new view controller. Start by dragging a UIButton onto the Main View Controller. You can double-click the button to add text – in the example it has been labeled Open NavCtlr. To actually create the segue: hold down the Ctrl key and click-drag from within the button to the Navigation Controller. A blue connector will be visible to indicate that a segue is being created.

When you mouse-up, the following menu appears to let you choose how the View Controller should be opened. Select Modal from this menu and the segue is created.

Now we’ll create a Navigation Controller segue; start by dragging another button, this time onto the Root View Controller. Then drag a View Controller onto the design surface and Ctrl-click and drag from the button into the new view Controller (as shown).

This time choose Push from the context menu.

Save the Storyboard and return to Xamarin Studio to run the application. You can navigate forward into the View Controller, but there is no way to dismiss the modal Root View Controller. This screenshot shows the navigation flow in the application (notice there is no way to return to the first view).

Drag another button (labeled Back to Main in the example) then select the entire View Controller – we are going to give it a custom name. In the right pane, choose the third icon so that you can see the Custom Class input as shown in the screenshot. In the sample the custom Root View Controller is called MonkeyController.

Hide the left pane by pressing the right-most View button, save & close the Storyboard then return to Xamarin Studio. A generated class will appear that matches the name MonkeyController. Viewing the class is not just a convenience in this article – you MUST switch back to Xamarin Studio to see the stub created, as this also generates the .h file that we are going to use in the next step!

Re-open the Storyboard, select the Back to Main button you created earlier and press the middle Editor button (tooltip: Show the Assistant editor). Xcode should look like this screenshot – if you do not see an ‘empty’ MonkeyController.h interface definition then something is wrong (try returning to Xamarin Studio to ensure the partial class has been created, then close and re-open the Storyboard).

Ctrl-drag from the button into the interface definition (as shown)

This will appear – change the Connection type from Outlet to Action

then give it a name – like clicked in this example – and press Connect.

Save the Storyboard again and return to Xamarin Studio. Open the MonkeyController.designer.cs file and observe that a partial method clicked has been created.

Open MonkeyController.cs to complete the partial method as shown.

Run the application again – you can now navigate between all the views using a combination of Storyboard segues and a custom clicked method.

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

An application can have its entire UI defined in a single Storyboard, or the UI can be broken down into multiple Storyboards. Storyboards are compiled into individual views to avoid any slowness associated with loading large scenes.

Instantiate Storyboards Manually

Sometimes applications have special requirements that can't be handled with the built-in storyboard transitions provided by Xcode. For example, in the following Storyboard, we may want to instantiate the two View Controllers manually, and program the transition ourselves:

  1. Manually instantiating storyboards requires a few extra steps. 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 Main:

  3. Open Main.storyboard and add a new Navigation Controller to the design space. Next, add a View Controller. Ctrl-drag from the Navigation to the View Controller to create a transition. Select root view controller under the Relationship Segue category:

  4. Select the View Controller by clicking at the top of the controller's frame. In Xcode's right panel, choose the Identity Inspector (third icon from the left). Here, we can specify a custom class as well as a unique ID for the View Controller. Set the custom class to MainViewController, and the Storyboard ID to MainViewController as well. Under Restoration ID, check the Use Storyboard ID box:

    Setting the Storyboard ID creates a View Controller class in Objective-C containing code-behind for the View Controller in the Storyboard. Later, we will link to this class, and create a managed C# instance of this class that we can work with it in Xamarin Studio. 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. Drag another View Controller onto the design space. In the Identity Inspector, set the custom class and Storyboard ID to YellowViewController, and check the Use Storyboard ID box:

  6. In the YellowViewController, select the View by clicking towards the center of the controller's frame. In Xcode's right panel, choose the Attributes inspector, and change the Background to yellow:

  7. Finally, drag a button onto the MainViewController, and add an Outlet named yellowButton:

  8. Save the XCode project and return to Xamarin Studio. Xamarin Studio will create custom classes for the View Controllers:

  9. Our storyboard is complete, but if we deploy the project now, we get a blank screen. That's because we still need to tell Xamarin Studio to use our storyboard, and to set up a root view controller to serve as the first View. We can do this in the AppDelegate class with the following code:

    
    UIWindow window;
    public static UIStoryboard Storyboard = UIStoryboard.FromName ("Main", 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, Main. 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.

  10. Next, open the MainViewcontroller.cs created from the storyboard. Note that Xamarin Studio has included a special constructor that includes a base class:

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

    In a previous step, we specified a Storyboard ID that created an Objective-C code-behind class for the Storyboard View Controller. This class is the base class for our View Controller, defined in Objective-C and referenced via a handle. To add code to the View Controller class, we need to register our C# instance of the View Controller so we can work with the View Controller in managed code.

  11. To register a class, add the [Register] attribute at the top of the class, and pass in a string identifier. The string identifier needs to match the Storyboard ID we specified in the previous step, to link the C# class to the corresponding Objective-C class:

    
    [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.

    Note: It's good practice to make the Storyboard ID and registeration identifier the same as the class name. This makes code easier to manage and avoids potantial for error.
  12. The last step in this class is to wire up the button and the transition to the yellow screen. We'll instantiate the YellowViewController from the Storyboard; then, we will program a push segue with PushViewController, as illustrated by the example code below:

    
    public MainViewController (IntPtr handle) : base (handle) 
    {
      this.Initialize ();
    }
    
    public void Initialize()
    {
      var myStoryboard = AppDelegate.Storyboard;
      yellowViewController = myStoryboard.InstantiateViewController ("YellowViewController") as YellowViewController;
    }
    
    public override void ViewDidLoad ()
    {
      base.ViewDidLoad ();
    
       yellowButton.TouchUpInside += (o, e) => {
        this.NavigationController.PushViewController(yellowViewController, true);
      };
    }
    
  13. Finally, let's register our YellowViewController. The class should look something like this:

    
    [Register("YellowViewController")]
    public partial class YellowViewController : UIViewController
    {
      public YellowViewController (IntPtr handle) : base (handle)
      {
      }
    }
    
  14. Running the application produces a 2-screen application:

Summary

This article provides step-by-step instructions to build simple application navigation using Storyboards. It discusses creating new view controllers, linking them together with segues, and creating actions to add C# code to events (like button touches). It also explores instantiating view controllers manually from an existing storyboard.