Running Node Modules in your iOS Project

RisingStack's services:

Sign up to our newsletter!

In this article:

Some day everybody loses their minds. I have lost mine last weekend…

Or not? I have decided that I will run one of my npm modules on my iPhone.
Is it possible? The short answer is yes, for the longer answer you should read this article. 😉

Background

Apple has introduced a native Objective-C API for JavaScriptCore in iOS 7 and you can use it in your iOS 8 Swift projects too. One can have multiple JavaScript virtual machines and contexts too.

What does it mean in practice?
You can evaluate any kind of JS code in your iOS application, call your methods, pass arguments and use the built-in JavaScript objects and methods like JSON.parse.

We have this super cool Node.js thing with the module system and we can transform our Node code with Browserify or WebPack to make it runnable in the browser. And this means that we can run this transformed code in our iOS application with the built-in JavaScriptCore of iOS. We have to do only one trick, assign this to window, because we do not have window in the core.

The how

1. Browserify

After you wrote your JavaScript code and exported your methods and variables with global.myMethod = function () {}, you should transform it with Browserify.

For this install Browserify with npm and browserify your code:

npm install -g browserify
browserify main.js -o bundle.js

2. The iOS side

We need a JavaScript environment to run our code, which can be done in the following way:

Do not forget to create a window variable and assign this to it, Browserify needs this.

// load the javascript file as a String
let path = NSBundle.mainBundle().pathForResource("bundle", ofType: "js")
var jsSource: String! = String.stringWithContentsOfFile(path!)

// Make browserify work
jsSource = "var window = this; \(jsSource)"

// create a javascript context environment and evaluate the script
var context = JSContext()

context.evaluateScript(jsSource)

The JavaScript object and the stringified JSON representation:

JavaScript object

The parsed JSON as a Swift dictionary output:

parsed JSON dictionary

3. Calling Javascript methods

You can get a reference for JavaScript objects with the objectForKeyedSubscript() and call your methods with the callWithArguments([]) with any piece of arguments.

// JSON parsing
let calculate = context.objectForKeyedSubscript("calculate")
let JSON = context.objectForKeyedSubscript("JSON")
let JSONparse = JSON.objectForKeyedSubscript("parse")
let JSONString = "{\"foo\":\"bar\",\"bar\":[1,2],\"world\":{\"hello\":4,\"foo\":\"bar\"}}"

let parsed = JSONparse.callWithArguments([JSONString])
let parsedDic = parsed.toDictionary()

Ok, what now?

Can this be a next step in the world of isomorphic JavaScript? Does anybody use it in production to share model, validation or any other business logic between the server and the client?

… and yes my liquid-pid npm module works perfectly in this way 😉

You can find the sample the code here.

The liquid-pid PWM’s output for temperature change visualized with swift-linechart:

Node.js code on iOS

Recommended reading

Share this post

Twitter
Facebook
LinkedIn
Reddit