D3 / JavaScript Swift & iOS | JavaScriptCore Framework

Why would you ever want to use JavaScript in your Swift Project?

javascript-sucks I am working on a project that started off as a web application first. It has a lot of cool features and some pretty advanced graphs. Their front end developer is using d3.js. D3.js is a JavaScript library for manipulating documents based on data. D3 is an amazing library that can do just about any kind of graph imaginable from circle packing to basic line graphs, and what is even more impressive is it was written by one guy Mike Bostock. Anyway in addition to awesome graphs there are a lot of helpful functions for calculating all kinds of data, and the front end developer on my project was using these. I thought no problem I can just translate these methods into swift and be able to reproduce the same data! Easy peasy lemon cheesy right. Wrong… Mike Bostock is a genius and I found out how incompetent I am at math!

A real world application

So in this application there is a graph that displays your co workers based on how much you interact with them based on email and slack conversations. The data base returns a score with each contact from 1 to 10 and according to that score the user is place in one of three rings the circle closet to you being those that you work with the most and the outer circle being the one that you work with the least. D3 has some really handy Quantitative Scales that the front end developer used to get which circle the co worker should be placed in. So after hours of trying to figure out how the hell Mike wrote these awesome scales I decided to embrace my hate, turn to the dark side and just use javascript in my project.
ain't nobody

JavaScriptCore Framework

Available since iOS 7 JavaScriptCore is the built-in JavaScript engine for WebKit. It currently implements ECMAScript as in ECMA-262 specification. It allows for an easy and fast way to interact with JavaScript.
To get started you first need to load in the d3 library. Also in this first step we are going to add error handling so we are able to see what we are doing wrong with our javascript which can be very handy!

// get a reference to the d3 library in our project
let fileLocation = NSBundle.mainBundle().pathForResource("d3.min", ofType: "js")!
// convert it to a string
let jsSource: String = try! String(contentsOfFile: fileLocation)
// create a javascript context environment
let context = JSContext()
// add exception handler so we can see any error that occur in our javascript
context.exceptionHandler = { context, exception in
    print("JS Error: \(exception)")
}
// load in the javascript into our context
context.evaluateScript(jsSource)

Once d3 is loaded we can access it exactly like you would in a HTML file

// create our javascript function for the linear scale we also mix in swift with the maxAmount variale
context.evaluateScript("circles = d3.scale.quantize().domain([0,\(maxAmount)]).range([3, 2, 1])")

// loop through all the contacts to determine which circle they should be placed in
for contact in contacts {
    // get the circle number based on score it will return 1, 2 or 3
    let circle: JSValue = context.evaluateScript("radius_circles(\(contact.score))");
    //  cast the JSValue to Int
    contact.circle = Int(circle.toInt32())
}
// sort the contacts array based on the new circle value
self.contacts.sortInPlace({ $0.circle < $1.circle })

Success

Thats all there is to it! Now we have data that matches the web app so we can successful show the same rankings and data in the iOS app! I don't think I would use this very often but I think it is very handy to have as an extra tool in your tool box. Let me know in the comments below what you guys think to this approach and if you would ever use javascript in your project

Lets be friends

I love meeting new iOS friends online so follow me on twitter
. Please stop by and say hello!

Author: barrettbreshears

I don't take showers, only blood baths.