MonoTouch and our first experiences

Wissenswertes
2 Kommentare

Leider ist der Eintrag nur auf Amerikanisches Englisch verfügbar. Der Inhalt wird unten in einer verfügbaren Sprache angezeigt. Klicken Sie auf den Link, um die aktuelle Sprache zu ändern.

MonoTouch allows developers to create C# and .NET based applications that run on Apple’s iPhone and Apple’s iPod Touch devices, while taking advantage of the iPhone APIs and reusing both code and libraries that have been built for .NET, as well as existing skills.

Some weeks ago we started the development of an iPhone version of taskmind. We decided to use MonoTouch because of the reasons stated above – reusing existing C# code and open source 3rd party libraries as well as .NET libraries, thus we didn’t need to learn Objective C or rewrite existing C# code.

The first steps using MonoTouch are quite simple, install the iPhone SDK, MonoTouch and MonoDevelop (the optional IDE you can use for building MonoTouch apps), rebuild existing code you want to use in the iPhone app and create some user interface code. With MonoTouch you can use Apple’s Interface Builder to create the UI and also the native iPhone Simulator to run/debug a MonoTouch iPhone app.

After some time I tried to launch a second instance of MonoDevelop on my Mac OS. But if you try to launch it again, Mac OS just switches to the open application. In a terminal you can force to open a new instance via the option “-n”:

open -n /Applications/MonoDevelop.app

Another thing I did not like was that MonoDevelop started in German (my Mac OS is installed in German). To launch MonoDevelop in English, run the following command in a terminal:

LANG=en_US.UTF-8 open -n /Applications/MonoDevelop.app

Now my development environment was configured as I prefer it. So I could start to create my app step by step and test it with the simulator. I was surprised, web requests, (de)serialization, persistence (SQLite, file system),… everything worked fine on the simulator.

Once my first prototype of taskmind was implemented and tested on the iPhone Simulator I wanted to test the app on my iPhone device. Therefore I registered for the Apple iPhone Developer Program and created a Development Certificate and Provisioning Profile and installed them using Xcode. These certificates are necessary to deploy an app for testing on a device. MonoTouch immediately detected the certificate and profile and I was able to deploy my app to my iPhone within the MonoDevelop IDE. But when I started the app, it crashed with an exception; and this was the beginning of a long story where I tried to find reasons and solutions why an exception occured …

… but let me tell the story step by step.

  • The first exception was the following:Unhandled Exception: System.ExecutionEngineException: Attempting to JIT compile method '......' while running with --aot-only.

    I googled it and found that MonoTouch does not support generic virtual methods. (http://monotouch.net/Documentation/Limitations#Generic_Virtual_Methods). This also means that generic methods declared in interfaces are not supported. However, generic methods which are not declared as virtual can be called without problems. Once I had changed all virtual generic methods in my code to non-generic ones, the exceptions did not appear again. But I got another one, although it successfully ran on the iPhone Simulator:

  • The exception was thrown during creating a directory:
    Directory.CreateDirectory(
      Path.Combine(
        Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)),
      “.config”);

    causes

    Unhandled Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.UnauthorizedAccessException: Access to the path "/private/var/mobile/Applications/AAEF9A93-1CA5-40C1-8E63-C08B800B1CFF/.config" is denied.

    The reason is that apps on the iPhone have limited access to the file system, only Environment.SpecialFolder.Personal is allowed. A problem description and solution can be found here: http://wiki.monotouch.net/HowTo/Files/HowTo:_Store_Files. I solved the problem and launched my app again and got the next exception.

  • I found the following output in my console:
    Ran out of trampolines of type 2 in '/private/var/mobile/Applications/2E7E28C5-8560-45E2-9696-2BE6902F19D8/tm-iphone-all.app/mscorlib.dll' (128)
    Stacktrace:
    at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication.UIApplicationMain (int,string[],intptr,intptr)

    Again I googled and found a quite similar problem: http://monotouch.net/Documentation/Troubleshoot#Ran_out_of_trampolines_of_type_1. I tried to compile and run my app with the described extra argument but it didn’t solve my problem (as expected because my error message was “out of trampolines of type 2” and not “type 1”). I found nothing on the internet, so I contacted the MonoTouch team. They told me that there is another argument I should try, namely “-aot "nimt-trampolines=2048"“. With this option my app successfully started on the iPhone device (after I have installed the latest Enterprise edition).

    Another pitfall I came across while trying some extra arguments is that you must select the correct configuration and platform in the settings dialog (be sure that iPhone is selected as the Platform and not iPhoneSimulator because otherwise the argument is not considered if you deploy to a device):
    MonoTouch settings

  • The next exception that occurred was related to generics again. I created a Hello World application and tried to reproduce the problem. The following piece of code:
    namespace DeviceTest { 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 { // This method is invoked when the application has loaded  // its UI and its ready to run public override bool FinishedLaunching(UIApplication app, NSDictionary opt) { window.MakeKeyAndVisible ();   try { var myTypeObject = new MyType<object> (); } catch (Exception ex) { Console.WriteLine ("First: " + ex.Message); } try { var myTypeString = new MyType<string> (); } catch (Exception ex) { Console.WriteLine ("Second: " + ex.Message); } return true; }   // This method is required in iPhoneOS 3.0 public override void OnActivated (UIApplication application) { } }   class MyType<T> { public MyType () { var list = new System.Collections.Generic.Dictionary<long?, T>(); } } }

    produces the following output if you run it on a device:

    First: Attempting to JIT compile method 'System.Collections.Generic.Dictionary`2<System.Nullable`1, object>:.ctor ()' while running with --aot-only.

    Second: Attempting to JIT compile method ‘System.Collections.Generic.Dictionary`2<System.Nullable`1, string>:.ctor ()’ while running with –aot-only.

    I think the problem is that the concrete types of Dictionary are not known at compile time. In the MonoTouch documentation you can read the following: “Unlike traditional Mono/.NET, code on the iPhone is statically compiled ahead of time instead of being compiled on demand by a JIT compiler.”. As a workaround I inserted the declarations of the instantiated Dictionary types somewhere in the code:

    System.Collections.Generic.Dictionary<long?, object> dummyObject; System.Collections.Generic.Dictionary<long?, string> dummyString;

    This is the only working solution I have found so far.

Now my app (which contains 3rd party libraries and thousands of lines of platform code) is running without any exception but I am not sure if I really eliminated all possible problems in my code.

To sum it up, MonoTouch is a great tool to create native iPhone apps using C# and the .NET libraries, but it has some limitations and pitfalls you have to keep in mind. All the exceptions described above were thrown when I tested my app on a real iPhone device; on the simulator everything worked, I had no problems. So you see that testing on a device is really necessary and can be quite challenging. You can use MonoDevelop as an IDE for developing MonoTouch iPhone apps. Although MonoDevelop has some rendering issues on Mac OS and although it is far away from being a sophisticated IDE like Xcode, Visual Studio or Eclipse, I am quite happy with it and I like the possibility to implement iPhone apps in C#.

 

Vorheriger Beitrag
26. Wispri: Erfolgreiche Karrieremuster
Nächster Beitrag
27. Wispri: Wird man mit Scrum und XP auch automatisch “Lean”?

Related Posts

2 Kommentare. Hinterlasse eine Antwort

Just did my very first iPhone app this weekend. I’m really excited, that I managed to create a (small but working) application in just 2 days. What also made me exciting is the fact that I could copy large code over from my WinForms applications and only do tiny adjustments to use it on MonoTouch.

Antworten

@Uwe
The great thing is that you cannot only copy the code, but you can create a common platform where you can reuse code for iOS and Windows Phone development as well as for other C# based applications. And what we did is, that we implemented a source-to-source translation from C# to Java, so we can use the same common platform for iOS, Windows Phone (C#), Android and Blackberry (Java). This source-to-source translation can be used for arbitrary C# code, not only for mobile development. So our benefit is, that we can use the same common components for all mobile OS and only have to implement the UI code. If you’re interested about that – just ask us 🙂

Antworten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Bitte füllen Sie dieses Feld aus
Bitte füllen Sie dieses Feld aus
Bitte gib eine gültige E-Mail-Adresse ein.
Sie müssen den Bedingungen zustimmen, um fortzufahren

Menü