What I’m trying to achieve with this post is to reduce the gap between native application development and hybrid application development. Xamarin is doing a pretty good job by creating an interface to use the native Swift frameworks. But how about a third party framework that you or your company has built for your own. How can we use that same Swift framework in a Xamarin environment? Let’s start development. The very first thing that you need to understand is, languages, syntaxes and the way of doing things will change time to time. Therefore first I will provide my working environment details.
1. Xcode version – 10.2
2. Swift version – 4.2.1
3. Deployment target – 10.0
First, you need to create a new Xcode project.
This time you are going to create a Cocoa Touch Framework under iOS category.
Then fill the basic details in the next pop up window and make sure to select Swift language, instead of Objective C.
Once the project load, next thing we need to do is, creating a new file inside that project like below.
That file content should be a Cocoa Touch Class.
In the next pop up window, you can give a name to that class, but you must make sure the class should be a subclass of NSObject. That’s one of the important thing you have to remember if you need your class to be visible inside a Xamarin project.
For the simplicity, I will make sure that our Swift framework does only one functionality, which is adding two numbers that passes to the function in the framework. That makes our class simple as below.
Make sure you have added @objc annotation and open keyword for both class and the function in order to make visible those inside the Xamarin project. When I declare the @objc annotation to the class, I have added class name inside the parenthesis. The reason for that is, if you have not done that the build tools will create a random name when it creates ApiDefinitions file, which you will be learn later in this post.
That’s all about coding and our next mission is to create a new target.
It should be an Aggregate target which comes under Cross-platform.
What I am going to do is creating a universal framework by including most commonly used iOS architectures without exiting the Xcode. In the next pop up window, provide a Product Name as below.
Under the newly created target, we need to run some commands, which we normally do inside a Run Script.
What goes inside the Run Script is shown below with the description as a comment of each line.
Don’t just copy and paste as it is. Try to understand what has been written and why. In that script there are some build settings parameters have included. And we have used xcodebuild command. Location of the xcodebuild path is below.
You might wonder, how I can know or where I can find these, what are the exact parameters I should use etc. Do not worry. Those do not magically appear. They are the Xcode project build settings, which you can see by running the following command.
Before build project, the next step is to set build configurations as Release. You can open that pop up window like below.
Next, set build configuration as Release and remove the tick from the Shared box.
The last thing is related to your universal target that you have created. What I’m going to achieve here is include latest as well as old architectures to our framework, then we can use this framework even in somewhat old iPhones as well. I’ve added missing architectures as below.
If I explain little bit about this architecture, iOS is going to stop supporting for 32 bit and moving on with 64 bits. I wanted this framework to support both 32 bit and 64 bit. That’s why I added x86 architecture which is 32 bit supports. Furthermore, like I mentioned in very early stage of this post, the Deployment Target is set to 10.0. Now you are good to build your framework target and universal target. First you build your framework target and then universal target. Make sure you have selected Generic iOS Device option like below.
Because of the last line of the Run Script, a finder window will open where you can see your build framework. At this point you have successfully created a Swift framework that can be integrate with a Xamarin iOS project. Before going to that integration part, I will tell you, how to verify that your fat file is supported for all the architectures that you have enabled in Xcode settings. What you have to do is, open your terminal application and go inside to your newly created framework directory and run below command.
If you get an output like below, which means that your framework will run on both 32 and 64 bit OS.
Architectures in the fat file: AroshaFramework are: i386 x86_64 armv7 arm64
Source for this project can be access in my GitLab repository
Let’s move to the next part of the post, that is integrating the Swift framework to a Xamarin iOS project. I’m not going to go through in details description of creating a sample Xamarin solution. If you are so naive, just follow this post, which has more than enough details of creating a Xamarin solution. Once you have created a basic solution, you need to add one more project to that.
The project that you are going to add, is a Binding Library project.
Next, refer the fat file inside your Swift framework with the Xamarin Binding Library.
After finishing that, you have to modify the ApiDefinition.cs file. Here, I recommend using Objective Sharpie tool. As for my knowledge, Xamarin still does not support direct binding with Swift. That’s why we need Objective C interface as a helper. Once you install that tool, you have to run the following command by going inside the Headers directory of the Swift framework.
If you have a curious mind, you may be questioning yourself, where the iphoneos12.1 parameter came from. Again, there is no magic with these commands, everything has a purpose and a meaning. That is the current iPhone OS which installed inside my Mac. How you find is? Just run below command.
Back to the topic. We were in the middle of editing ApiDefinition.cs file. After you ran the bind command it will create ApiDefinitions.cs (with extra s) file where your Swift header files are. Open that ApiDefinitions.cs file and just copy what you need and paste inside your project’s ApiDefinition.cs. The appropriate code will be like below.
Next step is to figure out each Swift package that is related to your Swift framework which you will be adding as NuGet packages inside your Xamarin iOS project. To do that, go inside your Swift framework directory again and run following command.
By looking at the above output, you can add necessary Swift NuGet packages. Worst case, if you have followed the steps accurately, you will end up with an error by saying that there are some conflicts between Swift packages you have added. In such a case just try to add the lower version of that conflicting occurring Swift Nuget package.
Last, but not least, what you want to do is access your precious framework inside your Xamarin iOS code. To do that, you have to add the binding project to your main project. Here is how you do it.
1. Expand the main project (Ex. UsageOfSwiftFramework.iOS)
2. Right click on the References and select Edit References
3. Then tap on the Projects tab
4. Then tick the project that you need to refer (Ex. BindingSwift)
Now you are good to call the Swift framework functions inside your ViewController.
I believe this is the end of this descriptive post. You can access this Xamarin code source from my GitLab repository. If you encounter any issues, just reach me from the comments. Wish you all a happy coding…!!!