Cross Platform
Android
iOS
Mac
Test Cloud

Hello, Mac

This guide walks through creating a first Xamarin.Mac application, and in the process introduces the development toolchain, including Xamarin Studio, and Xcode (and Interface Builder). It also introduces outlets, which expose controls to code, and finally, it illustrates how to build and run a Xamarin.Mac application to test it.

Overview

Using Xamarin.Mac, you can create native Mac applications by using the same UI controls that you would if you were writing the application in Objective-C and Xcode, except you have the flexibility and elegance of a modern language ( C#), the power of the .NET Base Class Library ( BCL), and a first-class IDE ( Xamarin Studio) at your fingertips.

Additionally, Xamarin.Mac integrates directly with Xcode so that you can use the integrated Interface Builder ( IB) to create your application’s user interface.

In this tutorial, we’re going to walk through creating a simple application from start to finish. We’ll cover the following items:

  • Xamarin Studio (MD) – Introduction to the Xamarin IDE (Xamarin Studio) and how to create Xamarin.Mac applications with it.
  • Anatomy of a Xamarin.Mac Application – What a Xamarin.Mac application consists of.
  • Xcode’s Interface Builder – How to use Xcode’s Interface Builder to define your application’s user interface (UI).
  • Outlets and Actions – How to use Outlets and Actions to wire up controls in the UI.
  • Deployment/Testing – How to run your application and test it out.

The following is a screenshot of the application that we’re going to build, running in Mountain Lion (Mac OS X 10.8):

Let’s jump in.

Introduction to Xamarin Studio

Nearly all Xamarin.Mac tutorials are based on using Xamarin Studio as the Integrated Development Environment (IDE) of choice. Xamarin Studio is a free, open-source IDE, and is very similar to other IDEs such as Eclipse or Visual Studio.

Let’s begin by launching Xamarin Studio. You can find it in either your Applications directory, or via a Spotlight search for “Xamarin Studio.”

Xamarin Studio should open up and look something like the following:

Let’s jump right in and begin our first Xamarin.Mac application.

Creating a New Xamarin.Mac Project

From the Xamarin Studio Home screen, choose Start a New Solution:

In the left-hand pane, choose C# > Xamarin.Mac, and then, in the center pane, select Xamarin.Mac Project template. This will create a new single window Mac application.

If you are using the trial, select "Mac (open source)" which uses the more limited set of APIs.

Let’s name it Hello_Mac. Choose a location where you’d like the solution to reside, and click OK.

Xamarin Studio will create a new Xamarin.Mac application and solution that looks something like the following:

This should be pretty familiar territory if you’ve used an IDE before. There is a Solution Explorer “pad” that shows all the files in the solution, and a code editor pad that allows you to view and edit the selected file.

Xamarin Studio uses Solutions and Projects, the exact same way that Visual Studio does. A solution is a container that can hold one or more projects; projects can include applications, supporting libraries, test applications, etc. In this case, Xamarin Studio has created both a solution and an application project for you. If you wanted to, you could create code library projects that the application project uses, just as you would if you were building a standard .NET application.

The Project

If you’re familiar with iOS programming, you’ll notice a lot of similarities here. In fact, iOS uses the CocoaTouch framework, which is a slimmed-town version of Cocoa, used by Mac. In fact, a lot of concepts will cross over here.

Let’s take a look at the files in the project:

  • Main.cs – This contains the main entry point of the application. When the application is launched, this contains the very first class and method that is run.
  • AppDelegate.cs – This file contains the main application class that is responsible for listening to events from the operating system.
  • Info.plist – This file contains application properties such as the application name, icons, etc.
  • MainMenu.xib – This is the UI for the application menu. .Xib files (also referred to as Nibs for legacy reasons), are XML files that contain the definition of views (UI elements).
  • MainWindow.cs – This is the class that represents the main window and controls the lifecycle of it.
  • MainWindow.designer.cs – This file contains plumbing code that helps you integrate with the main screen’s user interface.
  • MainWindow.xib – The UI for the main window.
  • MainWindowController.cs – This is the controller for the main window. We’ll cover controllers in the next guide, but for now, a controller can be thought of the main engine of any particular view.

Let’s take a quick look through some of these files. We’ll explore them in more detail later, and in other tutorials, but it’s a good idea to understand their basics now.

Main.cs

The Main.cs file is very simple. It contains a static Main method which creates a new Xamarin.Mac application instance and passes the name of the class that will handle OS events, which in our case is the AppDelegate class:

using System;
using System.Drawing;
using MonoMac.Foundation;
using MonoMac.AppKit;
using MonoMac.ObjCRuntime;

namespace Hello_Mac
{
        class MainClass
        {
                static void Main (string[] args)
                {
                        NSApplication.Init ();
                        NSApplication.Main (args);
                }
        }
}

AppDelegate.cs

The AppDelegate.cs file contains our AppDelegate class, which is responsible for creating our window and listening to OS events:

using System;
using System.Drawing;
using MonoMac.Foundation;
using MonoMac.AppKit;
using MonoMac.ObjCRuntime;

namespace Hello_Mac
{
        public partial class AppDelegate : NSApplicationDelegate
        {
                MainWindowController mainWindowController;

                public AppDelegate ()
                {
                }

                public override void FinishedLaunching 
(NSObject notification)
                {
                        mainWindowController = new MainWindowController ();
                        mainWindowController.Window
.MakeKeyAndOrderFront (this);
                }
        }
}

This code is probably unfamiliar unless you’ve built an iOS application before, but it’s fairly simple. Let’s examine the important lines.

First, let’s take a look at the two class-level variable declarations:

MainWindowController mainWindowController;

The MainWindowController declaration represents what controls the actual application window. Generally, for every window you create (and for many other things within windows), there is a controller, which is responsible for the window’s life cycle, such as showing it, adding new views (controls) to it, etc.

Cocoa (and by derivation, CocoaTouch) uses what’s known as the Model View Controller (MVC) pattern. We’ll examine this in more depth in the next tutorial, when we create an application with multiple windows.

Next, we have the FinishedLaunching method. This method runs after the application has been instantiated, and it’s responsible for actually creating the application window and beginning the process of displaying the view in it.

The first line instantiates a new instance of our main window controller:

mainWindowController = new MainWindowController ();

Next, the code tells the main window (the Window property on the controller) that it should be in focus and accept user input ( Key), and appear in the front of any other windows:

mainWindowController.Window.MakeKeyAndOrderFront (this);

MainWindowController.cs

As we’ve already seen, the MainWindowController class is our main window’s controller. That means it’s responsible for the life cycle of the main window. We’re going to examine this in detail later, so we can skip any more detail about it for now:

using System;
using System.Collections.Generic;
using System.Linq;
using MonoMac.Foundation;
using MonoMac.AppKit;

namespace Hello_Mac
{
        public partial class MainWindowController : MonoMac.AppKit.NSWindowController
        {
                #region Constructors

                // Called when created from unmanaged code
                public MainWindowController (IntPtr handle) : base (handle)
                {
                        Initialize ();
                }

                // Called when created directly from a XIB file
                [Export ("initWithCoder:")]
                public MainWindowController (NSCoder coder) : base (coder)
                {
                        Initialize ();
                }

                // Call to load from the XIB/NIB file
                public MainWindowController () : base ("MainWindow")
                {
                        Initialize ();
                }

                // Shared initialization code
                void Initialize ()
                {
                }

                #endregion

                //strongly typed window accessor
                public new MainWindow Window {
                        get {
                                return (MainWindow)base.Window;
                        }
                }
        }
}

The Window property is a convenience property that casts the base.Window property to a strongly-typed version of the actual Window class, so that any properties on there (as we’ll see later) are available without having to cast it every time you want to access them.

MainWindow.Designer.cs

The designer file for the Main Window class is empty right now, but it will be automatically populated by Xamarin Studio as we create our UI:

namespace Hello_Mac
{

        // Should subclass MonoMac.AppKit.NSWindow
        [MonoMac.Foundation.Register("MainWindow")]
        public partial class MainWindow
        {
        }

        // Should subclass MonoMac.AppKit.NSWindowController
        [MonoMac.Foundation.Register("MainWindowController")]
        public partial class MainWindowController
        {
        }
}

We aren’t usually concerned with designer files, as they’re just automatically managed by Xamarin Studio and just provide the requisite pluming code that allows access to controls that we add to any window or view in our application.

Now that we have created our Xamarin.Mac application and we have a basic understanding of its components, let’s jump over to Xcode and create our UI.

Introduction to Xcode and Interface Builder

As part of Xcode, Apple has created a tool called Interface Builder (IB), which allows you to create your UI visually in a designer. Xamarin.Mac integrates fluently with IB, allowing you to create your UI with the same tools that Objective-C users do.

It’s important to note that you don’t have to use IB to create your UI; you can also build it programmatically.

Let’s go ahead and walk through how to use IB to define our UI. Double-click on the MainWindow .xib file in Xamarin Studio. This should launch Xcode and look something like the following:

If Xcode doesn’t open up, you can right-click on the file and choose Open With : Xcode.

Let’s do a quick overview of Xcode to orient ourselves.

Components of Xcode

When you open a Xib in Xcode from MD, Xcode opens with the Navigator Area on the left and the Editor Area in the middle, and the Utilities Area on the right:

When a .xib file is open, the Editor Area surface is what’s known as Interface Builder (IB).

In previous versions of Xcode, IB was a separate application. If you don’t see the Utilities Area, you can make it display by clicking the far-right button in the View section of the toolbar:

The Utility Area is mostly empty because nothing is selected; however, if you select a control (or the main view), it will populate. The Utility Area is further broken down into two sub-areas, Inspector Tabs and Library Tabs:

In the Library Tabs Area, you can find controls and objects to place into the designer. The Inspector Tabs are kind of like property pages, where you can examine and edit control instances in the designer.

There are 8 different Inspector Tabs, as shown in the following illustration:

From left-to-right, these tabs are:

  • File Inspector – New in Interface Builder 4, the File Inspector shows file information, such as the file name and location of the Xib file that is being edited.
  • Quick Help – Also new in Interface Builder 4, the Quick Help tab is part of Xcode 4’s redesigned help system. It provides contextual help based on what is selected in Xcode.
  • Identity Inspector – The Identity Inspector provides information about the selected control/view.
  • Attributes Inspector – The Attributes Inspector allows you to customize various attributes of the selected control/view.
  • Size Inspector – The Size Inspector allows you to control the size and resizing behavior of the selected control/view.
  • Connections Inspector – The Connections Inspector shows the Outlet and Action connections of the selected controls. We’ll examine Outlets and Actions in just a moment.
  • Bindings Inspector – The Bindings Inspector allows you to configure controls so that their values are automatically bound to data models.
  • View Effects Inspector – The View Effects Inspector allows you to specify effects on the controls, such as animations.

Creating the Interface

Now that we’re familiar with the Xcode IDE and IB, let’s actually use IB to create the UI of our main view. We’re going to use IB to create the following:

To create this UI:

  1. Drag a Push Button and a L abel to the designer from the third tab of the Library.
  2. To resize the controls, select them and then pull on their resize handles.
  3. Double-click on the button to set its text.
  4. Make the label nearly as wide as the view. This will let us update the label with text when the buttons are clicked.

As you’re resizing and moving controls around, you’ll notice that IB gives you helpful snap hints that are based on Apple’s Human Interface Guidelines (HIG). These guidelines will help you create high quality applications that will have a familiar look and feel for Mac users.

While we have IB open, let’s look at one other useful area, the Document Inspector. The Document Inspector is just to the left of the Editor Area and can be expanded by clicking the > arrow button at the bottom of the area:

The Document Inspector shows you all of the items in a tree and allows you to select them:

 

If you have a complicated UI, this can be a great alternative to using the designer window.

OK, now that we have created our UI, we need to wire up our Outlets to code.

Outlets and Actions

Xamarin Studio created a file called MainWindow Controller.h as part of the Xcode project it generated to use the designer. This .h file is a stub file that Xamarin Studio created to mirror the Designer.cs file. This is where we’ll use Xcode to define our Outlets. Xamarin Studio will then synchronize the changes to this file with the designer file.

Outlets + Actions Defined

So what are Outlets and Actions? In traditional .NET UI programming, a control in the UI is automatically exposed as a property when it’s added. Things work differently in Mac (and in iOS programming, for that matter). Simply adding a control to a view doesn’t make it accessible to code. In order to access our controls from code, Apple gives us two options:

  • Outlets – Outlets are analogous to properties. If you wire up a control to an Outlet, it’s exposed to your code via a property, so you can do things like attach event handlers, call methods on it, etc.
  • Actions – Actions are analogous to the command pattern in WPF. For example, when an Action is performed on a control, say a button click, the control will automatically call a method in your code. Actions are powerful and convenient because you can wire up many controls to the same Action.

In Xcode 4, Outlets and Actions are added directly in code via Control-dragging. More specifically, this means that in order to create an Outlet or Action, you choose which control element you’d like to add an Outlet or Action, hold down the Control button on the keyboard, and drag that control directly into your code.

For Xamarin.Mac developers, this means that you drag into the Objective-C stub files that correspond to the C# file where you want to create the Outlet or Action.

In order to facilitate this, Xcode 4 introduced a split-view in the Editor Area called the Assistant Editor that allows two files to be visible at once (the .xib file in the Interface Builder designer, and the code file in the code editor).

In order to view the Assistant Editor split screen, click the middle button of the Editor choice buttons in the toolbar:

Xcode will then show the designer and .h file at once:

Now we can start wiring up our Outlets, we won’t use Actions in this application, but the process is nearly exactly the same.

Adding an Outlet

Before we start to wire up our Outlets, we first need to make sure that they’re going to get wired up in the right file. In the Assistant Editor, choose the file drop down just above the editor, and make sure that the MainWindowController.h file is chosen:

In this case, we could wire up the Outlets to the window file, but in practice, Outlets are should nearly always be put in controllers (where they’ll be used). So we’ll get in the habit now.

Once we’ve made sure that the right file is chosen, let’s perform the following procedure to create our Outlets:

  1. Determine for which control you want an Outlet. To start with, we’re going to create an outlet for the Click Me button.
  2. Hold down the Control key on the keyboard, and then drag from the control to an empty space in your code file after the @interface definition:

You can drag from the Document Inspector as well, which can be helpful if you have a complicated UI with nested controls.

A popover will then show, giving you the option to choose either Outlet or Action. Choose Outlet and name it ClickMeButton:

Click Connect after you’ve filled out the form, and Xcode will insert the appropriate code in the .h file:

Save the file, and then go back to Xamarin Studio. In the MainWindow.designer.cs file we should now see our new Outlet exposed as a property on the MainWindowController class:

Note that this is a partial class, so that Xamarin Studio doesn’t have to edit our MainWindowController.cs file.

As you can see, Xamarin Studio listens for changes to the .h file, and then automatically synchronizes those changes in the respective designer.cs file to expose them to your application.

We need to create one more Outlet for our label, so let’s switch back over to Xcode. Create the label’s Outlet the same way we did the button’s Outlet and name it OutputLabel. The .h file should have the following Outlets now defined:

@property (assign) IBOutlet NSButton *ClickMeButton;
@property (assign) IBOutlet NSTextField *OutputLabel;

Now that we have our Outlets wired up, let’s save the files and switch back to Xamarin Studio to actually do something interesting with them.

Note:

It probably took a long time to create the UI and Outlets for our first application, and it may seem like a lot of work, but we’ve introduced a lot of new concepts and we’ve spent a lot of time covering new ground. Once you’ve practiced awhile working with IB, this interface and all its Outlets can be created in just a minute or two.

Writing the Code

In our application, every time the first button is clicked, we’re going to update our label to show how many times the button has been clicked. In order to accomplish this, we need to do two things. First, we need to create a class-level variable in our MainWindowController class to track the number of clicks that have happened:

public partial class MainWindowController : 
MonoMac.AppKit.NSWindowController
{
        protected int numberOfTimesClicked = 0;
        …
}

Next, in the same class ( MainWindowController), we need to override the AwakeFromNib method and add some code to update our label with the number of times the button was clicked:

public override void AwakeFromNib ()
{
        base.AwakeFromNib ();
        ClickMeButton.Activated += (object sender, EventArgs e) => {
                numberOfTimesClicked++;
                OutputLabel.StringValue = "Clicked " + 
numberOfTimesClicked + " times.";
        };
}

We need to use AwakeFromNib, instead of another method such as Initialize, because AwakeFromNib is called after the OS has loaded the UI from the .xib file. If we tried to access the button control before the .xib file has been fully hydrated, we’d get a NullReferenceException error because the button control would not be created yet.

Also notice that we used the Activated event on the button. It’s kind of a strange name but it’s the event that gets raised when the button is clicked.

That’s it! We’ve created our first Xamarin.Mac application, so now it’s time to run it and test it!

Testing the Application

It’s time to build and run our application; to see it in action and make sure it runs as expected. We can build and run all in one step, or we can build it without running it.

Let’s build it first, just to learn how to build without deploying. Whenever we build an application, we can choose what kind of build we want:

  • Debug – A debug build is compiled into an .app (application) file with a bunch of extra metadata that allows us to debug what’s happening while the application is running.
  • Release – A release build also creates an .app file, but it doesn’t include debug information, so it’s smaller and executes faster.
  • AppStore – An AppStore build creates a signed application package that is ready to submit to the App Store.

In our case, we just want a debug build, so let’s make sure that Debug|x86 is selected in the build drop down:

Then, either press ⌘+B, or from the Build menu, choose Build All. If there are no errors, you’ll see a Build Succeeded message in the status bar of Xamarin Studio. If there are errors, review your procedure and make sure that you’ve followed the steps correctly. Start by confirming that your code (both in Xcode and in Xamarin Studio) matches the code in the tutorial.

Running the Application

To run the application, we have three options:

  • Press ⌘+Enter
  • From the Run menu, choose Debug
  • Click the Gear icon with the green circle from the build toolbar.

The application will build (if it hasn’t been built already) and if we click the button a few times, we should see something like following:

Congrats, you’ve now built and run your very first Xamarin.Mac application!

Summary

Congratulations! We covered a lot of ground here, but if you followed this tutorial from start to finish, you should now have a solid understanding of the components of a Xamarin.Mac application as well as the tools used to create them.

In the next guide, we’re going to take a look at the Model, View, Controller (MVC) pattern in Mac and how it’s used to create more complex applications.