Creating a binding for Swift frameworks in Xamarin

Xamarin is one of the more popular platforms for developers to build apps across platforms. In our goal to make it easy for developers to integrate the HyperTrack SDK into their apps we were looking to support the Xamarin developer community. This turned out to be harder than we initially thought because Xamarin does not directly support Swift frameworks. We ended up building a binding for our Swift framework in Xamarin.iOS so Xamarin developers could integrate the HyperTrack SDK for iOS. If you are Swift developer looking to make your framework work for Xamarin you will like this post. If you are a Xamarin developer looking to build live location features in your app with high accuracy and low battery consumption you will love this post.

Problem

The HyperTrack framework for iOS is written in Swift which in turn has dynamic framework dependencies through CocoaPods. Now how do we make it work for Xamarin? After doing a bit of research and looking at various forums we found that Xamarin does not directly support Swift frameworks. A few blogs talk about binding objective-C libraries and static Swift frameworks but there are no guides for Swift frameworks with multiple dependencies. Since that was a blocker for us we started playing with our Swift framework and better understanding Xamarin. After days of frustration we drew inspiration from Xamarin’s official Objective C Binding document and an awesome stackoverflow answer to build a proper binding of the Hypertrack SDK to be used in an Xamarin.iOS project. Since CocoaPods is popular among developers other developers might be facing similar issues to make their Swift frameworks work for the Xamarin community.

Solution

Step 1: Building the Swift framework in the right way

1.1.      Ensure the Objective-C compatibility of the interface through which developers will communicate with your framework. Your interface class and public functions should have the “@objc” annotation.

1.2.     Set the Enable Bitcode flag as No. This will prevent optimizations by LLVM while creating binaries.

1.3.      Set the Enable Bitcode to No for all dependencies if you are using CocoaPods.

1.4.       Change your framework scheme to run in Release mode so it builds for all the architectures (armv7 armv7s arm64)

1.5.      Now build your framework for Generic iOS Devices and then for a simulator. Go to the framework in Finder. Copy ‘Release-iphoneos’ and ‘Release-iphonesimulator’ to your Desktop.

Step 2: Building a fat binary

For the uninitiated a fat binary is a binary that contains multiple executables. Here we will create a fat binary that has executables of armv7 armv7s x86_64 and i386.

2.1. Create the FAT library using:

lipo -create Release-iphonesimulator/NAME.framework/NAME Release-iphoneos/NAME.framework/NAME -output NAME.framework/NAME

2.2. Copy the files in Release-iphonesimulator/NAME.framework/Modules/NAME.swiftmodule to NAME.framework/Modules/NAME.swiftmodule (so far it only contained files from the iphoneos)

2.3. Do this for all dependent projects in your framework that you link though Pods. Finally you will have a bunch of frameworks with fat binaries in them.
Use lipo -info command on your binaries to see if they contain all the architecture.

Step 3: Configuring Xamarin binding project to use our fat frameworks

3.1.      Add Native References of all the frameworks including your main and dependent frameworks.

3.2.      Create the ApiDefinition based on Namd-Swift.h file inside headers folder in your main framework. Use Objective Sharpie to create it for you.

The basic command will be something like: sharpie bind -sdk iphoneos9.3 NAME-Swift.h

3.3.      Now copy the content of ApiDefinition.cs to your binding’s ApiDefinition.cs.

Step 4: Configuring your app to use the binding of the Swift Framework

4.1.    Add the binding to your project by adding a reference to the binding or adding a dll generated by the binding.

4.2.      After that add Swift packages to your app. Remember that Xamarin.iOS does not provide official support for binding a Swift library. So you must manually include the Swift core libraries in the Frameworks and SwiftSupport folders. You will also need to include all the Swift core frameworks used in your framework.

Are you building location features in your app?

And hey if you are building live location features in your app using any platform – Xamarin iOS Android React Native others – give HyperTrack a look. We will help you build those features with near-zero battery consumption high accuracy and minimal development effort.