This blog post is a walkthrough for setting up an iPhone application that uses UINavigationController to move between two screens. It shows how to use MonoDevelop and Interface Builder to create the application. MonoTouch is Novell’s implementation of the .NET framework that runs on Apple’s mobile devices, and provides a managed wrapper around Apple’s CocoaTouch UI toolkit. It allows you to write iPhone apps in C#. Interface Builder (IB) is Apple’s drag-and-drop designer for creating UIs, like Expression Blend in the Microsoft world. When you install MonoTouch part of the installation process requires IB to be installed as well.
First let’s see the demo application in action. When it launches you see the “home” screen:
After tapping the “Go to sub view” button the “sub” view slides into place:
The first step is to start MonoDevelop (which is the Visual Studio for Mono developers). Create a new iPhone Window-based project:
Right-click on the project in the Solution window and select Add | New File… | iPhone View with Controller. Name the new item HomeViewController, as seen below:
Then add another iPhone View with Controller to the project, this time name it SubViewController:
After you have completed the previous steps, your Solution window should look like this:
At this point we have two empty views (and controllers) that we can display in our iPhone application. By default they will not be shown, so we need to hook up a UINavigationController object in the application that will show and hide these views. UINavigationController maintains a stack of UIViewController objects and allows you to programmatically specify which controller/view to show. We can easily add one to our program in Interface Builder. To open IB, double-click on MainWindow.xib in MonoDevelop’s Solution window. Once it is open, click the Objects tab in the Library window, locate the “Navigation Controller” item, and drag-drop it onto the MainWindow.xib window. After doing that, your screen should look something like this:
Next we need a way to reference that UINavigationController object from our AppDelegate class. AppDelegate is the CocoaTouch equivalent of the Application class in WPF and Silverlight programs. In order to have a reference to the nav controller, we must add an “outlet” to the AppDelegate class. An outlet is the way that Interface Builder allows you to reference the UI objects it creates from your code.
To add the outlet, go to the Library window, select the Classes tab, search for “appdel” in the search box below, and the select the “AppDelegate” item from the list. Then open the dropdown box and select “Outlets” to view the list of outlets. Click the “+” button to add a new outlet, name it “navController” and set the Type to “UINavigationController.” The result should look like this:
At this point we have indicated that our program’s AppDelegate class (which was created for us by MonoDevelop) has a property called ‘navController’ of type UINavigationController. Next we need to explain to Interface Builder where our AppDelegate instance get its value from. To do that, go to the MainWindow.xib window, right-click on the App Delegate object, and the Outlets window will appear.
Notice that our ‘navController’ outlet is in the list, but it is not connected to anything yet. To connect it to a UINavigationController instance, click on the empty circle on the right and drag it over the “Navigation Controller” item beneath the “App Delegate” item.
That bluish line appears as you drag from the empty circle to a UINavigationController object on the screen. When you release the left mouse button, the outlet will be connected to the object under the mouse cursor.
At this point our AppDelegate class can reference the UINavigationController that we added to MainWindow. We will see why this is necessary later. For now, let’s start setting up the navigation controller so that it knows what view to display first. To do that, expand the Navigation Controller item in the MainWindow.xib window and select the Root View Controller item. Then go to the Attributes windows and set NIB Name to “HomeViewController” so that the navigation controller knows which XIB to initially load (a NIB is a “compiled” XIB, similar to how BAML is compiled XAML in WPF).
IMPORTANT: Be sure to next select the ‘Identity’ tab on the right and set the Class to “HomeViewController” as well. If you don’t do this, after adding outlets to the HomeViewController, you will get a runtime error of “this class is not key value coding-compliant for the key XXX.” That error occurs because the default Class of the root view controller is UIViewController, which does not have your outlets defined on it. By specifying the Class of the controller, the correct type information will be used at runtime and the error will not occur.
After you configure the controller as described above, the Root View Controller design surface indicates where the root/initial View comes from, as seen below:
Now it’s time to create the Home screen. Go back into MonoDevelop, open the Solution window, and double-click on HomeViewController.xib to open it in Interface Builder. Once it’s open, drag a UIButton from the Library onto the View that opened for the HomeViewController. Change the button’s text to “Go to sub view.”
Next add an outlet to HomeViewController called “subViewButton” of type UIButton.
It’s time to hook up that new outlet to the “Go to sub view” button created earlier. To do that, go to the HomeViewController.xib window, right-click the “File’s Owner” item, and drag from the new outlet to the UIButton item.
We’re done setting up the HomeViewController. Next go back into MonoDevelop and double-click the SubViewController.xib file in Solution window to open it in IB. Drag a UIButton onto the new View, and change its text to “Go home.” Add an outlet to SubViewController called “homeButton” of type UIButton. Then connect that outlet to the button on the view. Note that in the screenshot below I’m connecting it to the button on the design surface, which has the same effect as the approach used before:
We are done using Interface Builder, so save and go back to MonoDevelop. Open Main.cs and include the line of code that adds the navController’s View as a sub-view of the window. This is how our “home” view is added to the UI.
The ‘navController’ property is available because we added an outlet to our AppDelegate class. The view that it references is our home view. We must now write some code that causes that view’s button to navigate to the SubView.
Lastly we must add code to SubViewController that makes the “Go home” button work.
That’s it, we are done!