Guide to Building iOS Applications with MonoTouch for the .NET/C# Developer
Use your.NET/C# skills to develop iPhone and iPad applications
March 28, 2011
RELATED: "Build an iPad Application Using MonoTouch, C#, and .NET" and "Working with Images and Animation on the iPhone and iPad with .NET and C#: Part 1"
The Apple iPhone has taken the mobile world by storm since its original release in 2007. At that time, the only way to target the iPhonfie was either by writing a web application or by jailbreaking the phone. Neither was a good option. Writing a web application for the iPhone is not difficult, but it doesn't take advantage of the native capabilities of the device. Jailbreaking an iPhone relies on the owner of the device installing a piece of software that sidesteps the iPhone's security schemes and official distribution mechanisms. The process also raises several issues:
Jailbreaking requires the iPhone owner to perform the operation. Many iPhone users are not technically proficient enough to do this.
Jailbreaking involves some unknown quantities: How well can an iPhone be upgraded to new versions of the iPhone OS? Will jailbreaking an iPhone open it up to security issues? And so on.
In 2008, Apple made it possible to run applications directly on the iPhone and introduced the App Store, opening the possibility of a development ecosystem that could target the device's capabilities. These capabilities include amazing graphics, sound, background processing, and other features that were, at that time, revolutionary in a mobile device. The iPhone is the leader of the smartphone pack in terms of integrating support for telephone service, apps, web access, and music in one consumer-friendly package.
How Do .NET Developers Fit into the Picture?
.NET developers, the largest set of developers in the general software development ecosystem, have looked at the iPhone with a high degree of envy. There are many stories about developers working a relatively short amount of time, submitting an application to the App Store, and quickly making hundreds of thousands of dollars. A recent report by the IT market research company Yankee Group states that sales of smartphone applications will increase from $343 million in 2009 to $4.3 billion in 2013.
In 2009, Novell announced a version of its Mono .NET-compatible open source development platform that's designed to run within the iPhone as a native application. This version of Mono, named MonoTouch, generated significant excitement within the .NET community. MonoTouch lets .NET developers take a portion of their existing development knowledge and use that to build applications that run on the iPhone. Although you can't take an existing .NET application and run that application on the iPhone, developers can apply their knowledge to building iPhone applications. I liken this to you, as an American, going to England and speaking the British dialect. You know the same basic language; but the accents, mannerisms, and certain terms are different.
When you build a MonoTouch application for the iPhone, you require a different set of tools:
Apple Macintosh: It's not a big surprise that you must have a Mac that runs at least OS X 10.6.x (at the time of this writing).
iPhone SDK: MonoTouch requires the Apple iPhone SDK. The iPhone SDK contains the iPhone emulator, which allows an application to be tested without having to be deployed to the device.
Mono Framework: MonoTouch requires the open source Mono Framework, which is an implementation of .NET guided by Novell and hosted at mono-project.com.
MonoTouch Framework: MonoTouch is a .NET layer, licensed by Novell, which covers the iPhone features that are exposed through CocoaTouch. MonoTouch Framework is available at monotouch.net and is available in several different versions.
MonoDevelop: MonoDevelop is the standard tool for developing through Mono and MonoTouch. MonoDevelop is the tool that this article will use. It is available at monodevelop.com.
Xcode: Xcode is Apple's development tool. It has several good features for writing code that targets the iPhone. This article does not directly use Xcode, but Xcode includes several tools that you can use together with MonoDevelop to debug against the iPhone.
Development Strategies
Several strategies are available for .NET developers to build applications for the iPhone. They are:
web development by using ASP.NET: building a web-based application in ASP.NET that directly targets the iPhone web browser.
using MonoDevelop and MonoTouch: the strategy covered in this article
using Visual Studio .NET and MonoDevelop: using Visual Studio to create the non-UI part of your application, debug in Visual Studio, then using that code in the MonoTouch application that will be deployed to the iPhone.
Web development by using ASP.NET. The iPhone is bundled together with the Safari web browser. The recent update to the iPhone/iOS 4.x OS provides iPhone users a mobile version of the Safari 4.x browser. Many .NET developers are working in ASP.NET. It is possible to build a web-based application in ASP.NET that directly targets the iPhone web browser. There are pros and cons to this strategy.
The major advantage is the deployment of new versions of the application. New versions are directly available to iPhone users the moment the deployment is made to a web server. There is no need to wait for an application to be accepted by the App Store and for users to download it. By making a web application directly available to users, the App Store can be bypassed. Developers can stay in their existing development environments and use the tools with which they are most familiar.
The major disadvantage is that a web application will have limited support for taking advantage of the app's native features. Whenever a user experiences a bad connection over the 3G network or loses a Wi-Fi connection, the user cannot load the full application. The Safari browser in the iPhone does offer offline support. But if the application does not take advantage of the offline features in the browser, the user is out of luck.
There are several levels to creating an ASP.NET application that targets the iPhone. At the basic compatible level, a web app is compatible with Safari on the iPhone. The next level is a web-optimized application to target Safari on the iPhone. An optimized app recognizes that it is running on Safari and can take advantage of Safari features when the browser is detected. Finally, a developer can build a web application that specifically targets Safari on the iPhone simply because Safari runs on the iPhone. However, this approach also requires the most development time of the options for ASP.NET web developers.
MonoDevelop and MonoTouch. When you develop by using MonoTouch, your primary tool will be MonoDevelop. MonoDevelop lets you build native applications that run on the iPhone.by applying your .NET development knowledge.
Visual Studio .NET and MonoDevelop. There is no getting around the requirement of using a Mac that has the iPhone SDK installed to deploy an application to the iPhone. At some point, the .NET developer must leave behind the Visual Studio development platform. A strategy for MonoTouch development is for developers to use Visual Studio for creating the non-UI of their applications, debug in Visual Studio, then use that code in their MonoTouch application. This strategy works well for reusing existing logic. This logic can be encapsulated into classes that can be carried over to MonoDevelop, recompiled, and deployed to the iPhone. There are several ways to handle this:
A Windows-based computer can be used to host Visual Studio to develop certain basic pieces of code. That code can then be moved to a Mac that’s running MonoDevelop and MonoTouch to be used within the MonoDevelop/MonoTouch application.
Visual Studio can be hosted within a vmware-style guest session. The code can then be moved into the host that’s running MonoDevelop/MonoTouch.
The only problem with this approach is that there’s a danger of implementing some code that is available in.NET but isn't available on the MonoTouch platform.
What Is MonoTouch?
The MonoTouch API is a combination of the .NET 3.5 Framework core features and the APIs on the iPhone. MonoTouch provides a bridge (interop) between the iPhone's native APIs, which are based on Objective-C and C-based APIs, to the .NET world to which C# developers are accustomed.
MonoTouch has the following components:
The Monotouch.dll, a C# assembly that provides a binding API for the iPhone's native APIs. The supported native APIs include Quartz, Core Animation, and the other APIs of the iPhone.
A command-line SDK that can compile C# and Common Intermediate Language (CIL) code. This compiled code can be run in the simulator or on an actual iPhone.
An add-in to MonoDevelop that enables iPhone development and lets the Interface Builder be used to create graphical applications.
A commercial license of the Mono runtime. A commercial license enables the static linking of the Mono runtime to the developed code.
iPhone Requirements
iOS does not support just-in-time (JIT) compilation or the sharing of libraries between applications. The lack of support for JIT compilation occurs at the iPhone kernel level and is a technical limitation of the iPhone. This is a problem for .NET development. In .NET development, source code (VB, C#, or other languages) is compiled to Microsoft Intermediate Language (MSIL). After the executable is set to run on an actual system, the JIT process compiles the MSIL code into actual code that takes advantage of the hardware on which the code is running. The iOS also does not allow the sharing of libraries between different applications on the device. As developers almost certainly know, Apple is not shy about enforcement in regards to iOS, so developers must be vigilant to meet the company’s requirements.
MonoTouch meets these requirements by being a static compiler. MonoTouch emits executables that run as native applications. There is no JIT or scripting involved, so the contractual and technical requirements are met for running on the iPhone. MonoTouch does this by using the Mono Project's Ahead of Time compilation feature, which is beyond this general discussion.
MonoTouch does have several limitations, mostly centered on code limitations:
It does not work with System.Reflection.Emit.
It cannot work with Dynamic Language Runtime (DLR) or with any languages that depend upon DLR. It also cannot support any attempt to generate code at runtime.
It does not allow support for System.Runtime.Remoting.
It does not support dynamic creation of types.
The built-in Ahead of Time support limits the support for .NET Generics. This limited support means that the following operations are not supported:
Generic Virtual Methods
P/Invodes in Generic Types
Property.SetInfo on a Nullable
Using a Value type as a Dictionary Key can create issues. By default, a Dictionary constructor tries to use EqualityComparer.Default, which, in turn, uses Reflection to instantiate a new type. This works for Reference types because the create step is not performed. For most value types, the creation is performed. The attempt at creation results in the error.
Additional limitations are listed at monotouch.net/Documentation/Limitations.
Namespaces and Classes
MonoTouch provides a rich set of namespaces and classes to support building applications for the iPhone. The most popular namespaces and classes are:
MonoTouch.ObjCRuntime: This namespace provides the interop/bridge between the .NET/C# world and the Objective-C world of the iPhone.
MonoTouch.Foundation: This namespace provides support for the data types necessary to communicate with the Objective-C world of the iPhone. Most types are directly mapped. For example, the NSObject ObjectiveC base class is mapped to the MonoTouch.Foundation.NSObject class in C#. Some classes are not directly mapped but are instead mapped to their native .NET types. For example, NSString maps to the basic string type and NSArray maps to a strongly typed array.
MonoTouch.UIKit: This namespace provides a direct mapping between the UI components within Cocoa Touch. The mapping is done by providing .NET classes for each UI component. This is the namespace that developers will spend most of their time working with. For .NET developers, Cocoa Touch is an abstraction layer or API for building programs that run in the iPhone. Cocoa Touch is based on the Cocoa API used in building programs that run on Mac OS X. Cocoa Touch can be thought of as Cocoa tuned for the touch-based iPhone operating system.
OpenTK: This namespace is a modified version of the OpenTK API. OpenTK is an object-oriented binding for Open Graphics Library (OpenGL). OpenGL is an API for using three-dimensional graphics. OpenTK is a library for performing OpenGL, OpenAL, and OpenCL. OpenTK is written in C# and runs on Windows, Mac OS X, and Linux. The OpenTK implementation on the iPhone has been updated to use CoreGraphics and to expose only the functionality that’s available on the iPhone.
Introduction to Development on the Mac with MonoDevelop
Your process of building an application starts by using MonoDevelop, then running the application in the iPhone simulator, and finally deploying the application to an iPhone. MonoDevelop is the software development tool for Mono on the Mac. MonoDevelop is available for Windows, Mac OS, and several flavors of Linux; however, we will concentrate on MonoDevelop for the Mac.
MonoDevelop for the Mac is a new product. It was officially released with MonoDevelop 2.2. MonoDevelop is an IDE for developing by using Mono/.NET, C#, and other languages. MonoDevelop can be used to create iPhone applications, desktop applications, and web applications that use WebForms and the Model-View-Controller architecture. Currently, MonoDevelop is at version 2.4.
Because this is most likely the first time you are running MonoDevelop, I’ll explain the process in excruciating detail to address any questions that may arise. After you start MonoDevelop, create an iPhone application. To do this, point to New on the File menu, click Solution, and select an iPhone application to create. Figure 1 shows the process of creating an iPhone application.
Figure 1: Creating an iPhone application
By default, the new solution is displayed on the left side of MonoDevelop, as shown in Figure 2.
Figure 2: A newly created solution displayed in MonoDevelop
Figure 3 shows the MonoDevelop interface.
Figure 3: MonoDevelop Interface Builder design surface
The solution is displayed in addition to the following:
The Specific Project: The project in this case is IntroToMonoTouch.
References: The references are a list of the namespaces that are included in this project. Although MonoTouch includes a set of standard references, you may have to add some namespaces, such as Linq.
Main.cs: This is the default startup template used by MonoTouch. It has the Main() method. The Main() method is the starting point for an iPhone application and also starts the event loop for handling interaction between the iPhone and the application.
MainWindow.xib: This file defines the UI for an application and is typically modified in Interface Builder. Interface Builder uses some slightly different concepts than those of Visual Studio and its design surface.
MainWindows.xib.designer.cs: This file contains definitions of the views, controls, outlets, and actions in the UI. This file is updated each time that the UI is updated through Interface Builder. You should not update this file manually.
Other files: As you add other files to your project, they are displayed in the Solution Explorer.
Interface Builder
Interface Builder is the development tool for creating the application interface (see Figure 3). When Interface Builder starts, a blank design surface is displayed. You can drag controls from the Library onto the design surface and arrange them to create the necessary UI. For Visual Studio developers, this is a familiar concept.
Outlets. The concept of outlets is particularly confusing for developers who are first learning about MonoTouch and building iPhone apps. This term is used throughout the Apple developer website and the MonoTouch website. An outlet is a private pointer to a UI object, and it’s visible only within the class in which it is defined.
After you arrange the controls on the design surface, you must define their outlets in the application delegate. To create the outlets, click the plus sign (+) button in the Outlets section of the App Delegate Connections window. This step is shown in Figure 4.
Figure 4: Creating outlets for the application delegate
Figure 5 shows the code for the MainWindow.designer.xib.cs file.
// ------------------------------------------------------------------------------// // This code was generated by a tool.// Mono Runtime Version: 2.0.50727.1433// // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated.// // ------------------------------------------------------------------------------namespace IntroToMonoTouch {// Base type probably should be MonoTouch.Foundation.NSObject or subclass[MonoTouch.Foundation.Register("AppDelegate")]public partial class AppDelegate {private MonoTouch.UIKit.UIWindow __mt_window;private MonoTouch.UIKit.UILabel __mt_TimesTouchedLabel;private MonoTouch.UIKit.UIButton __mt_TouchMeButton;#pragma warning disable 0169[MonoTouch.Foundation.Connect("window")]private MonoTouch.UIKit.UIWindow window {get {this.__mt_window = ((MonoTouch.UIKit.UIWindow)(this.GetNativeField("window")));return this.__mt_window;}set {this.__mt_window = value;this.SetNativeField("window", value);}}[MonoTouch.Foundation.Connect("TimesTouchedLabel")]private MonoTouch.UIKit.UILabel TimesTouchedLabel {get {this.__mt_TimesTouchedLabel = ((MonoTouch.UIKit.UILabel)(this.GetNativeField("TimesTouchedLabel")));return this.__mt_TimesTouchedLabel;}set {this.__mt_TimesTouchedLabel = value;this.SetNativeField("TimesTouchedLabel", value);}}[MonoTouch.Foundation.Connect("TouchMeButton")]private MonoTouch.UIKit.UIButton TouchMeButton {get {this.__mt_TouchMeButton = ((MonoTouch.UIKit.UIButton)(this.GetNativeField("TouchMeButton")));return this.__mt_TouchMeButton;}set {this.__mt_TouchMeButton = value;this.SetNativeField("TouchMeButton", value);}}}}
There are a couple of interesting items to note in the code:
A partial class is created. The partial class AppDelegate allows the contents of this file to be compiled by using the content of the AppDelegate partial class as defined in the Main.cs file.
The connections as defined are private. If the connections had to be made available to another class, you would have to define connections to the class.
Now that the basics of the application are set up, you can get down to writing the application logic. Figure 6 shows the code for the Main.cs file.
using System;using System.Collections.Generic;using System.Linq;using MonoTouch.Foundation;using MonoTouch.UIKit;namespace IntroToMonoTouch{public class Application{static void Main (string[] args){UIApplication.Main (args);}}// The name AppDelegate is referenced in the MainWindow.xib file.public partial class AppDelegate : UIApplicationDelegate{private Int32 count = 0;private string TouchString = "{0} Times Clicked";// This method is invoked when the application has loaded its UI and its ready to runpublic override bool FinishedLaunching (UIApplication app, NSDictionary options){// If you have defined a view, add it here:// window.AddSubview (navigationController.View);TouchMeButton.TouchUpInside += HandleTouchMeButtonTouchUpInside;TimesTouchedLabel.Text = String.Empty;window.MakeKeyAndVisible ();return true;}void HandleTouchMeButtonTouchUpInside (object sender, EventArgs e){count++;TimesTouchedLabel.Text = String.Format(TouchString, count);}public override void DidEnterBackground (UIApplication application){}public override void WillEnterForeground (UIApplication application){}public override void ReceiveMemoryWarning (UIApplication application){}// This method is required in iPhoneOS 3.0public override void OnActivated (UIApplication application){}}}
In the Main.cs code, the AppDelegate class is a partial class. This lets it be compiled together with the connections as created in Interface Builder. By compiling the separate .cs file definitions together, the resulting code runs as if it were originally from the same file. This lets multiple programs (Interface Builder and MonoDevelop, in this case) have the responsibility of file and code management without the possibility of the programs easily writing over each other.
The AppDelegate class inherits from the UIApplicationDelegate class. The UIApplicationDelegate defines methods that are called by the UIApplication singleton that is created by a running application.
The methods that Figure 6 shows are as follows:
FinishedLaunching: This method is the startup event within iOS. This method is good for wiring up events. It is not a good place for long-running calculations because of the iPhone's built-in limit for starting applications.
HandleTouchMeButtonTouchUpInside: The HandleTouchMeButtonTouchUpInside method handles the TouchUpInside event of the TouchMeButton. In this code, the event updates a table on the screen. This event was created by the developer.
DidEnterBackground: The DidEnterBackground method is called when an application enters the background. This method is new in iOS 4.0. Although it’s not automatically included in the MonoTouch templates, this method is important if the application has to perform some kind of check when an application enters the background state. Such an action would be the user clicking the Home button.
WillEnterForeground: This method is called when an application that’s currently running in the background will start to enter the foreground. This method is new in iOS 4.0. Although it’s not automatically included in the MonoTouch templates, this method is important if the application has to perform some kind of check when the application is selected by the user while the app is currently in the background.
ReceiveMemoryWarning: This method is called when iOS sends out a low memory warning. Although this method is not included in the MonoTouch templates, it’s important if the application has to clean up some resources to free up memory.
Thankfully, MonoDevelop provides IntelliSense support in MonoDevelop. Figure 7 shows IntelliSense support for a button.
Figure 7: IntelliSense support for a button in MonoDevelop
Actions. Now that a UI is created, the application has to be able to respond to user events. For those familiar with Visual Studio, creating actions (also known as “handling events” in the Windows world) is a fairly easy concept. For a button in a WinForm or in a WebForm, double-clicking the button causes the following to occur: An event is defined in the control (WebForm) or in the Designer.cs file (WinForm), the source file opens, and the editor takes you to the click event. You can then add code to that event to perform whatever functionality is required. There is a similar, somewhat more manual process for doing this in MonoDevelop by using MonoTouch.
Creating outlets made the UI controls available to you and also available within the AppDelegate class. MonoDevelop allows the handling of user events; however, this is a manual process. To handle user events, open the Main.cs file and go to the FinishedLaunching() method within the AppDelegate class. To set up the touchdown event on a button (roughly the equivalent of a click event on a button in WinForms), add an event to the control's TouchDown property.
After you create the control event, you can build the application and deploy it to the simulator by pressing Command+B to build the application or Command+Enter to compile and deploy. Alternatively, you can click Build Menu, then click Run on the MonoDevelop menus. After the application is deployed to the simulator, you see a window that resembles the window in Figure 8.
Figure 8: The window you see after deploying an app to the MonoDevelop simulator
Deploying to an iPhone
Now that an application has been created and tested in the simulator, it's time to deploy and test the application on an actual device. This is a fairly short process, but it can be confusing. The key pieces of the process are as follows:
Developers are required to be members of the Apple iPhone Developer Program. The cost of this program is currently $99 per year.
You must request and install the Developer Certificate. You obtain this from Apple through your iPhone Developer Program membership. This Certificate should be visible within the development Mac's Keychain security utility.
You must request and install the Deployment Certificate. You obtain this from Apple through your iPhone Developer Program membership. This Certificate should be visible within the development Mac's Keychain security utility.
The iPhone must be properly provisioned. Luckily, Apple supplies a wizard through its developer web site that helps in the setup and provisioning of the iPhone.
After you set up the development system, you must set up the MonoDevelop project to deploy the application to the iPhone when the developer selects the option to deploy to the device. You will set the project options at the same time by navigating to Project Options @@> Build @@> iPhone Bundle Signing, as shown in Figure 9. In this window, you have to select the identity that is used.
Figure 9: Setting up the MonoDevelop project to deploy an application to the iPhone
Apple provides the following resources for setting up the certificates and deployment setup for Mac developers. To access these resources, you must be a member of the Apple iPhone Developer Program.
the iOS Developer Program website. (You must log in to view the rest of the resources.)
the iPhone Developer Program provisioning website
an Apple PDF document that describes the certificate process in detail
To properly deploy an application to a local computer during development, the iPhone must be running an OS version that’s compatible with the iPhone SDK installed on your Mac. The OS version of the directly connected iPhone cannot be newer than the SDK version. For example, the deployment will work if the iPhone OS version is 4.0 and the SDK version is 4.2, but it will fail if the iPhone OS version is 4.2 and the SDK version is 4.0. If you are working with incompatible OS versions, you must upgrade the SDK on the development computer to a more recent version that supports the OS version of the connected iPhone.
Using the SearchBar
Now that we've looked at MonoTouch, MonoDevelop, and development for the iPhone for .NET developers, I wanted to give you one final short example in which we'll use the iPhone's SearchBar. Although search data is typically used to perform some type of search, in this example the code will use the user input value from the SearchBar to populate a label.
To get this functionality to work, put a SearchBar into a Window in Interface Builder, and create an outlet. Save the outlet, and add the following lines of code to the FinishedLaunching method:
search.OnEditingStopped += HandleSearchOnEditingStopped;search.OnEditingStarted += HandleSearchOnEditingStarted;
The two event handlers are then defined as shown in Figure 10, and Figure 11 shows the output of this code. From a .NET standpoint, these are commands that make sense and that are easily understandable.
void HandleSearchOnEditingStarted (object sender, EventArgs e){//perform some search.search.ShowsCancelButton = true;}void HandleSearchOnEditingStopped (object sender, EventArgs e){//do something on the final search.output.Text = search.Text;search.ShowsCancelButton = false;}
Figure 11: Output from the SearchBar event handlers executable code
Expanded Opportunities
By using MonoTouch, .NET developers can now take their skills to the iPhone and iPad. I hope that this short look at MonoTouch and MonoDevelop motivates you to get started developing for these products. Considering the number of Apple devices in use and the potential income that they represent, you should definitely take a look at developing for such a large market. In fact, there’s no excuse not to look at developing for iPhone and iPad devices. And please stay in touch with me as you progress! I want to hear about the apps that you create.
Wallace B. "Wally" McClure ([email protected]) is a Microsoft MVP, ASPInsider, member of the national INETA Speakers Bureau, author of seven programming books (including two about MonoTouch), and a partner in Scalable Development. Currently, Wally is in the final stages of writing an Android programming book. He blogs at www.morewally.com and co-hosts the ASP.NET Podcast.
About the Author
You May Also Like