Objective-C bindings

Xamarin has developed a sophisticated system for calling native Objective-C libraries from C# in iOS projects. The core of Xamarin.iOS uses this same technology to call native Apple APIs in UIKit, CoreGraphics, and other iOS frameworks. Developers can create iOS binding projects to expose Objective-C classes and methods to C# using simple interfaces and attributes.

To aid in creating Objective-C bindings, Xamarin has created a small tool named Objective Sharpie that can process Objective-C header files for you and export the valid C# definitions to add to a binding project. This tool is a great starting point for most bindings that will get your binding three-fourths of the way complete. You will also want to hand edit and fine tune things to be more C# friendly in a lot of cases.

As an example, we will write a binding for the Google Analytics library for iOS. It is a simple and useful library that can track the user activity in your iOS or Android applications. At the time of writing, the version of the Google Analytics SDK was 3.02, so some of these instructions may change as new versions are released.

First download and install Objective Sharpie from http://tinyurl.com/ObjectiveSharpie and perform the following steps:

  1. Download the latest Google Analytics SDK for iOS available at https://tinyurl.com/GoogleAnalyticsForiOS.
  2. Create a new iOS Binding Project named GoogleAnalytics.iOS.
  3. Run Objective Sharpie.
  4. Select iOS 7.0 as the Target SDK and click on Next.
  5. Add all six of the header (*.h) files included with the Google Analytics SDK; you can find these in the Library folder of the download. Click on Next.
  6. Pick a suitable namespace such as GoogleAnalytics and click on Generate.
  7. Copy the resulting ApiDefinition.cs file that was generated into your iOS binding project.
  8. After a few seconds, your C# file will be generated. Click on Quit.

When finished, you should have not received any error messages from Objective Sharpie during the process, and your screen should look like the following screenshot:

Objective-C bindings

Now if you return to your binding project, you'll notice that Objective Sharpie has generated an interface definition for every class discovered in the header files of the library. It has also generated many enum values that the library uses and changed casing and naming conventions to follow C# more closely where possible.

As you read through the binding, you'll notice several C# attributes that define different aspects about the Objective-C library such as the following:

  • BaseType: This declares an interface as an Objective-C class. The base class (also called superclass) is passed in to the attribute. If it has no base class, NSObject should be used.
  • Export: This declares a method or property on an Objective-C class. A string that maps the Objective-C name to the C# name is passed in. Objective-C method names are generally in the following form: myMethod:someParam:someOtherParam.
  • Static: This marks a method or property as static in C#.
  • Bind: This is used on properties to map a getter or setter to a different Objective-C method. Objective-C properties can rename a getter or setter for a property.
  • NullAllowed: This allows null to be passed to a method or property. By default, an exception is thrown if this occurs.
  • Field: This declares an Objective-C field that is exposed as a public variable in C#.
  • Model: This identifies a class to Xamarin.iOS to have methods that can be optionally overridden. This is generally used on Objective-C delegates.
  • Internal: This flags the generated member with the C# internal keyword. It can be used to hide certain members that you don't want to expose to the outside world.
  • Abstract: This identifies an Objective-C method as required, which goes hand in hand with Model. In C# it will generate an abstract method.

The only other rule to know is how to define constructors. Xamarin had to invent a convention for this, since C# interfaces do not support constructors.

To define a constructor besides the default one, use the following code:

[Export("initWithFrame:")]
IntPtr Constructor(RectangleF frame);

This would define a constructor on the class that takes in RectangleF as a parameter. The method name, Constructor, and the return type, IntPtr, signal the Xamarin compiler to generate a constructor.

Now, let's return to our binding project to finish setting up everything. If you compile the project at this point, you'll get a few compiler errors. Let's fix them one by one as follows:

  1. Change the default namespace of the project to GoogleAnalytics. This setting is found in the project options under General | Main Settings.
  2. Add libGoogleAnalyticsServices.a from the SDK download to the project.
  3. Add using statements for MonoTouch.Foundation, MonoTouch.UIKit, and MonoTouch.ObjCRuntime at the top of the file.
  4. Remove the multiple duplicate declarations of GAILogLevel. You may also wish to move any enumerations to the StructsAndEnums.cs file.
  5. Remove the declaration for GAIErrorCode.
  6. In the SetAll method of GAIDictionaryBuilder, rename the params parameter to parameters, as params is a reserved word in C#.
  7. Remove the duplicate declarations for GAILogger, GAITracker, and GAITrackedViewController.
  8. Go through any Field declarations and change [Field("Foobar")] to [Field("Foobar", "__Internal")]. This tells the compiler where the field resides; in this case, it will be included internally in our binding project.
  9. Remove all the Verify attributes. These are spots where Objective-C Sharpie was unsure of the operation it performed. In our example, all of them are fine; so, it is safe to remove them.

After going through those issues, you should be able to compile the binding and get no errors. You could have read the Objective-C header files and written the definitions yourself by hand; however, using Objective Sharpie generally requires a lot less work.

At this point, if you tried to use the library in an iOS project, you would get an error such as the following:

Error MT5210: Native linking failed, undefined symbol: 
    _FooBar. Please verify that all the necessary frameworks 
    have been referenced and native libraries are properly 
    linked in.

We need to define the other frameworks and libraries that the Objective-C library uses. This is very similar to how references work in C#. If we review the Google Analytics documentation, it says that you must add CoreData, SystemConfiguration, and libz.dylib. Additionally, you must add a weak reference to AdSupport.

Open libGoogleAnalyticsServices.linkwith.cs that was created automatically nested underneath the *.a file and make the following changes:

[assembly: LinkWith ("libGoogleAnalyticsServices.a",LinkTarget.ArmV7 | LinkTarget.ArmV7s | LinkTarget.Simulator,LinkerFlags = "-lz",Frameworks = "CoreData SystemConfiguration",WeakFrameworks = "AdSupport",ForceLoad = true)]

We added references to frameworks in the following ways:

  • Frameworks: Add them to the Frameworks value on the LinkWith attribute, delimited by spaces.
  • Weak Frameworks: Add them to the WeakFrameworks property on the LinkWith attribute in the same manner. Weak frameworks are libraries that can be ignored if they are not found. In this case, AdSupport was added in iOS 6; however, this library will still work on older versions of iOS.
  • Dynamic Libraries: Libraries such as libz.dylib; can be declared in LinkerFlags. Generally, you drop the .dylib extension and replace lib with –l.

After these changes are implemented, you will be able to successfully use the library from iOS projects. For complete documentation on Objective-C bindings, visit the Xamarin documentation site at http://docs.xamarin.com/ios.

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

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