How to write an Ionic-Cordova plugin in Swift

Note: I am not the worlds best writer, but I just wanted to share some useful information with all of you.

So you’ve found out that the plugin that you’ve been using isn’t all it’s chopped up to be? Or better yet, you found an amazing Swift library, that does everything you want it to do, and more. Well, that was exactly the point that I had reached while surfing the plugin list that Ionic showcases.

Without further ado, here are my steps to produce a Swift plugin for Ionic/Cordova, as of September 27, 2018.

Github Setup

  1. Create a new Github repository that follows the Ionic-Cordova plugin naming conventions.
cordova-plugin-your-plugin-name

An example of this would be the Ionic-Native Camera plugin:

cordova-plugin-camera
Setting up the plugin GitHub repository.

2. Pull the repository down to your computer, so that we have something to work in.


Plugin Folders & File Creation

1. Within your local GitHub repository (that we just pulled down), add the following folders & files. Certain files are written in a particular naming convention, some are CamalCased, and some are not, please follow the naming convention that is written.

  • src/ios/YourPluginName.swift
  • www/YourPluginName.js
This is what your project folder setup should look like now.

You now have the basic folder setup, but unfortunately, this won’t work just yet. We have a few more files to create & edit. Ignore the files we just created for now. We’ll get back to them in a little bit.

2. Create & edit the package.json file.

Create your package.json file in the main project folder, and then copy & paste the below code. Make the edits, which are commented appropriately.

Note: Be sure to remove the commented lines from the package.json or else when you attempt to install the plugin to your main project, it will throw an error.
{
"name": "YourPluginName", // Your Plugin Name (CamalCased)
"version": "0.0.1", // Plugin version.
"description": "Your Plugin Description", // What you want the desc to say.
"cordova": {
"id": "cordova-plugin-your-plugin-name", // same as your Github Repo.
"platforms": [ // The platforms you're targeting.
"ios" // We're only targeting IOS for this tutorial.
]
},
"keywords": [ // Keywords that your plugin will be searched by.
"cordova",
"camera",
"ecosystem:cordova",
"cordova-ios",
],
"author": "Bengejd", // Your name
"license": "MIT" // The license you want (recommended to be MIT)
}

3. Create & edit the plugin.xml file

Create your plugin.xml file in the main project folder, and then copy & paste the below code. Make the edits, which are commented & bolded appropriately.

<?xml version='1.0' encoding='utf-8'?>
<plugin id="cordova-plugin-your-plugin-name" version="0.0.1"
xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android">
<name>YourPluginName</name>

<js-module name="YourPluginName" src="www/YourPluginName.js">
<clobbers target="YourPluginName" />
</js-module>

<platform name="ios">
<config-file target="config.xml" parent="/*">

<feature name="YourPluginName">
<param name="ios-package" value="YourPluginName" />
</feature>

</config-file>

<!-- Add in the plugin .swift files here -->
<source-file src="src/ios/YourPluginName.swift" />

<!-- Add in the swift-support plugin by default -->
<dependency id="cordova-plugin-add-swift-support" version="1.7.2"/>
</platform>
</plugin>
Note: Be sure to keep the cordova-plugin-add-swift-support plugin, as it will automatically create the header files for us when the user installs. This just makes it easier for the user to add the plugin, and have it working automatically. You can take this out, but the user would be responsible for handling the cordova-plugin-add-swift-support themselves, if they have a different version number.

Plugin code setup

  1. Now we’re going to be editing the src/ios/YourPluginName.swift file. The edits you need to make are bolded below. When you add additional functions, you’ll use a similar layout with your custom code instead of the template below.
/*
* Notes: The @objc shows that this class & function should be exposed to Cordova.
*/
@objc(YourPluginName) class YourPluginName : CDVPlugin {
@objc(yourFunctionName:) // Declare your function name.
func yourFunctionName(command: CDVInvokedUrlCommand) { // write the function code.
    /* 
* Always assume that the plugin will fail.
* Even if in this example, it can't.
*/
    // Set the plugin result to fail.
var pluginResult = CDVPluginResult (status: CDVCommandStatus_ERROR, messageAs: "The Plugin Failed");
    // Set the plugin result to succeed.
pluginResult = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: "The plugin succeeded");
    // Send the function result back to Cordova.
self.commandDelegate!.send(pluginResult, callbackId: command.callbackId);
}
}
Note: messageAs in the pluginResult can be aString, Int, Double, Bool, Array, Dictionary, ArrayBuffer, and Multipart . You can learn more about them on Cordova’s official docs.

That’s all it we need to do to the src/ios/YourPluginName.swift file.

2. Now we’re going to be editing the www/YourPluginName.js file

var exec = require('cordova/exec');

var PLUGIN_NAME = "YourPluginName"; // This is just for code completion uses.

var YourPluginName = function() {}; // This just makes it easier for
us to export all of the functions at once.
// All of your plugin functions go below this. 
// Note: We are not passing any options in the [] block for this, so make sure you include the empty [] block.
YourPluginName.yourFunctionName = function(onSuccess, onError) {
exec(onSuccess, onError, PLUGIN_NAME, "yourFunctionName", []);
};
module.exports = YourPluginName;

You now have all of the basic framework setup for your plugin. We’re not done just yet, but we’re done working with the plugin project folder for now.


Integration into Ionic-Native

Now we are going to create the Ionic-Native package so that our app can be properly imported and used in future projects.

The Ionic-Native repository we’ll be forking.
  1. Navigate to: https://github.com/ionic-team/ionic-native
  2. Fork the repo, and pull down a local copy to your computer.
  3. Open the ionic-native repo that we just pulled, in your favorite IDE, I personally use WebStorm.
  4. Now this is where it gets funky, I’ll list out what you need to do, but you can look at Ionic-Native’s developer docs for more help, if you need it.
  5. Within the Ionic-Native repository folder, navigate to src/@ionic-native/plugins/
  6. Now create a folder called your-plugin-name. This will be similar to your plugin’s Github repository name, minus the cordova-plugin part.
  7. In that folder, create a file called index.ts
  8. Inside our newly created index.ts file, copy & paste the below code. Make the edits, which are commented & bolded appropriately.
import { Injectable } from '@angular/core';
import { Cordova, IonicNativePlugin, Plugin } from '@ionic-native/core';
@Plugin({
pluginName: 'YourPluginName',
plugin: 'cordova-plugin-your-plugin-name',
pluginRef: 'YourPluginName',
repo:
'https://github.com/YOUR-REPO-LINK-HERE',
platforms: ['iOS']
})
@Injectable()
export class YourPluginName extends IonicNativePlugin {
 /**
* Your plugin plugin functions go here.
* Function names should match the ones in your .swift & .js files.
* Otherwise you won't be able to execute them.
*/
@Cordova({
successIndex: 0,
errorIndex: 1
})
yourFunctionName(): Promise<any> {
return;
}
}

9. Now within the ionic-native project, run the following commands npm install& npm run build this will build the project plugins listed in the /src/@ionic-native/plugins folder. When the command finishes running, our plugin package will be output to the/dist/@ionic-native/your-plugin-name folder. This is what we will use to test our plugin, before trying to pull-request our changes to the Ionic-Native repo.

10. Once the build process finishes (this may take a few mins), your plugin package will be output to the /dist/@ionic-native/your-plugin-name folder. Copy your-plugin-name folder, and navigate back to your main project (The Ionic project that you’re going to test the plugin in).

11. Now, I am assuming that you have built your node_modules by now, but if you haven’t, go ahead and run the command npm install and it’ll install your project dependencies.

12. Navigate to the node_modules/@ionic-native folder, and paste the copied folder your-plugin-name into the @ionic-native folder. So that it looks like node_modules/@ionic-native/your-plugin-name . After that, we are pretty much done! You can import the plugin into your project now, like you would any other package.

An example of your node_modules folder.
import {YourPluginName} from '@ionic-native/your-plugin-name';

And in your constructor statement:

private pluginName: PluginName

And then to use the plugin, all you have to do is call it directly. From a function:

public someFunctionName(){
this.yourPluginName.yourPluginFunction().then(() => {
console.log("The yourPluginFunction ran without errors!");
}).catch(err => {
console.log("yourPluginFunction encountered the following error: ",err);
})
}
Note: That in the future, if you run the command npm install or add/remove another plugin you’ll have to re-do steps 10–12.

Installing the plugin

Now that we have all of that stuff finished up, all we have to do is add the plugin to our project by running the following command in your project root.

cordova plugin add ~/path-to-your-plugin/YourPluginName

In the future, you can just add the plugin from the repository directly, like you would any other. But for now, we’re going to do it locally, since we’re testing.


Almost done

I wanted to add that you can directly edit the your-plugin-name.swift file in your Xcode yourProjectName.xcworkspace to test different things without having to remove and re-add the plugin each and every time you make a change. Though this is only limited to the YourPluginName.swift file, which is located in yourProjectName.xcworkspace/plugins/YourPluginName.swift .

If you make changes to your @ionic-native/plugins/your-plugin-name/index.ts file or your src/www/YourPluginName.js file, you’ll have to remove the plugin via:

cordova plugin rm YourPluginName
cordova plugin add ~/path-to-your-plugin/YourPluginName

Final notes

Now all you have left to do is push your plugin code to Github, push the @ionic-native local repo, and initiate a pull-request so that future users can install it directly from ionic-native, instead of having to do our testing workaround.

Note: Ionic-native has specific requirements for pull-requests about how to properly submit them without it getting rejected, so you might want to check them out.

Questions?

You can find me on:
- GitHub: https://github.com/bengejd/
- Medium: https://medium.com/@JordanBenge

Who am I? I am a Software Developer who loves helping others and contributing to Open-Source. I’ve been working in the Ionic Framework since Ionic 1, and have tried to keep up to date on the latest and greatest when it comes to Hybrid Mobile App Development.

If you enjoyed this story, please click the 👏 button and share to help others find it! Feel free to leave a comment below if you need any help.