Accessing native iOS APIs from JavaScript, via NativeScript

Alastair Coote
3 min readMar 7, 2016

--

I’m a web developer by trade, which means I’ve spent the last eight or so years jealously looking over at the world of native mobile development and the ever-increasing feature set it has to play with that I don’t. Push notifications, background downloading, native view controls, widgets… all beyond my reach. Like many web folk I’ve dipped my toes into that world with some prototypes and hack projects — slogged through Objective C, been delighted by Swift, been reassured that Java is still… well, really Java-y. But the core problem remains — the bulk of my work is always going to need to live on the web, so I can never fully jump over to the native side.

But a year or so ago, two projects appeared out of nowhere — React Native and NativeScript. Both promised to allow me to write cross-platform native apps with the JavaScript I already use every day. I’m fascinated by both, and in particular whether they have potential for those of us in the news-y publishing-y world that can’t afford to ignore the web.

React Native has by far the most community support, but the JavaScript you write lives inside its own world — if there isn’t a plugin for some native functionality you want, you have to drop down to Objective C or Swift to get it. NativeScript promises something more: complete native API availability via JavaScript. I wanted to write a really quick prototype (for detecting hostile mobile ads that redirect users to the App Store) and it seemed like the ideal chance to take NativeScript for a spin.

The setup

NativeScript uses Node for a lot of its scripting, but once you have that on your system, installing it is as simple as typing “npm install nativescript”. When you create a new project it adds some boilerplate code that includes NativeScript’s own XML format for defining views. It’s a fully-featured cross-platform UI library, but I wanted to ignore all of that for now as get as close as I could to a native setup — to just use the APIs themselves. So I wiped out all the files, and created a new app.ts file with the following:

const App = NSObject.extend({
applicationDidFinishLaunchingWithOptions: function (application, launchOptions) {
// Launch code here
}
}, {
protocols: [UIApplicationDelegate]
});

..and that’s really all you need to do to hook into application launch. You don’t even need to use TypeScript, but I figured I’d go all in, using Visual Studio Code to enable the TypeScript typeahead feature. It’s really quite slick:

With that initial hook, all I needed to do was declare a UIViewController with a UIWebView inside it:

export const DetectorController = UIViewController.extend({
init: function() {
this.webview = UIWebView.new()
.initWithFrame(UIScreen.mainScreen().bounds);

this.webview.delegate = this;
this.view = this.webview;
return this.super.init();
}
}, {
protocols: [UIWebViewDelegate]
})

and write my ad testing code inside that controller. I’ve put the entire repo on Github — it’s only a few dozen lines of code, but still. A proof of concept.

Conclusion

This experiment was all of an hour long, and this lunchtime writeup is even shorter than that, so I’m not going to draw any broad conclusions here.

It’s clear that NativeScript’s API access is incredibly powerful, but this example is essentially JavaScript for JavaScript’s sake — it would be simpler and easier to just write this in Swift. Debugging seems more complex than it would be in Xcode (though not having to use XCode is a perk), though there is potential for “live reload” functionality that would avoid constant rebuilds while developing.

The real potential here depends on whether NativeScript lives up to its cross-platform promise (you can access Android APIs the same way), and whether it improves communications with an embedded web view (WKWebView has much more advanced communication hooks — can we do direct JS-to-JS calls, I wonder?). The jury is still out on that, but I like what I’ve tried so far.

--

--

Alastair Coote

Doing mobile news-y stuff at @nytimes. Previously of @gdnmobilelab.