Using preprocessor statements

When using file linking or cloned projects files, one of your most powerful tools is the use of preprocessor statements. If you are unfamiliar with them, C# has the ability to define preprocessor variables such as #define IPHONE, and then using #if IPHONE or #if !IPHONE.

The following is a simple example of using this technique:

#if IPHONE
  Console.WriteLine("I am running on iOS");
#elif ANDROID
  Console.WriteLine("I am running on Android");
#else
  Console.WriteLine("I am running on ???");
#endif

In Xamarin Studio, you can define preprocessor variables in your project's options under Build | Compiler | Define Symbols, delimited with semicolons. These will be applied to the entire project. Be warned that you must set up these variables for each configuration setting in your solution (Debug and Release); it can be an easy step to miss. You can also define these variables at the top of any C# file by declaring #define IPHONE, but they will only be applied within the C# file.

Let's go over another example, assuming we want to implement a class to open URLs on each platform:

public static class Utility
{
  public static void OpenUrl(string url)
  {
    //Open the url in the native browser
  }
}

The preceding example is a perfect candidate for using preprocessor statements, since it is very specific to each platform and is a fairly simple function. To implement the method on iOS and Android, we will need to take advantage of some native APIs. Refactor the class to look like the following:

#if IPHONE
  //iOS using statements
  using MonoTouch.Foundation;
  using MonoTouch.UIKit;
#elif ANDROID
  //Android using statements
  using Android.App;
  using Android.Content;
  using Android.Net;
#else
  //Standard .Net using statement
  using System.Diagnostics;
#endif

public static class Utility
{
  #if ANDROID
    public static void OpenUrl(Activity activity, string url)
  #else
    public static void OpenUrl(string url)
  #endif
  {
    //Open the url in the native browser
    #if IPHONE
      UIApplication.SharedApplication.OpenUrl(NSUrl.FromString(url));
    #elif ANDROID
      var intent = new Intent(Intent.ActionView,Uri.Parse(url));
      activity.StartActivity(intent);
    #else
      Process.Start(url);
    #endif
  }
}

The preceding class supports three different types of projects: Android, iOS, and a standard Mono or .NET framework class library. In the case of iOS, we can perform the functionality with static classes available in Apple's APIs. Android is a little more problematic, and requires an Activity object for launching a browser natively. We get around this by modifying the input parameters on Android. Lastly, we have a plain .NET version that uses Process.Start() to launch a URL. It is important to note that using the third option would not work on iOS or Android natively, which necessitates our use of preprocessor statements.

Using preprocessor statements is not normally the cleanest or the best solution for cross-platform development. They are generally best used in a tight spot or for very simple functions. Code can easily get out of hand and can become very difficult to read with many #if statements, so it is always better to use it in moderation. Using inheritance or interfaces is generally a better solution when a class is mostly platform specific.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.134.118.95