iOS JavaScriptCore Tutorial for Beginners

Photo by Sung Shin on Unsplash
Photo by Sung Shin on Unsplash
The JavaScript engine built in iOS SDK is JavaScriptCore. JavaScriptCore currently supports ECMAScript 6 (2015).

JavaScript has been voted for the most popular language for several years. Many Hybrid Mobile App are also implemented using JavaScript, such as Cordova and React Native. The JavaScript engine built in iOS SDK is JavaScriptCore. JavaScriptCore currently supports ECMAScript 6 (2015). Let’s take a look at how to use JavaScriptCore.

JSContext & JSValue

JSContext

JSContext represents a JavaScript execution environment. You must use it to execute JavaScript code.

import JavaScriptCore
let context = JSContext()!

JSValue

When we pass a value or get an executed result from JavaScriptCore, their type will be JSValue.

context.evaluateScript(" function sum(a, b) { return a + b; } ")
let result1: JSValue = context.evaluateScript("sum(1, 1);")!
print(result1.toInt32()) // 2

Getting JavaScript Variables or Functions

We can use JSContext.objectForKeyedSubscript() to get a JavaScript variables or functions.

let sumFunc: JSValue = context.objectForKeyedSubscript("sum")
let result2 = sumFunc.call(withArguments: [2, 2])!
print(result2.toInt32()) // 4

Setting Swift Variables or Functions to JavaScript

JSContext.setObject() allows us to set Swift variables to JavaScript.

let price = 6
context.setObject(price, forKeyedSubscript: "price6" as NSString)
let result3 = context.evaluateScript("price6 * 3")!
print(result3.toInt32()) // 18

You can also set Swift functions to JavaScript.

let multiply: @convention(block) (Int, Int) -> Int = { $0 * $1 }
context.setObject(multiply, forKeyedSubscript: "multiply" as NSString)
let result4 = context.evaluateScript("multiply(3, 5);")!
print(result4.toInt32()) // 15

Setting Swift Objects to JavaScript

We can also set a Swift class to JavaScript.

First, you have to declare a protocol inheriting JSExport protocol, and declare a class implementing the protocol. And the protocol must be declared with @objc. In protocol, we can export properties and functions.

In the following code, we export class Coffee. Note that the init() cannot be exported, so we declare create().

@objc protocol CoffeeExports: JSExport {
    var name: String { get set }
    var price: Int { get set}
    
    func order(_ count: Int) -> Int
    
    static func create(_ name: String, _ price: Int) -> Coffee
}

class Coffee: NSObject, CoffeeExports {
    var name: String
    var price: Int
    
    required init(name: String, price: Int) {
        self.name = name
        self.price = price
    }
    
    func order(_ count: Int) -> Int {
        return price * count
    }
    
    static func create(_ name: String, _ price: Int) -> Coffee {
        Coffee(name: name, price: price)
    }
}

Then use JSContext.setObject() to export Coffee.

context.setObject(Coffee.self, forKeyedSubscript: "Coffee" as NSString)
let result5 = contextevaluateScript("""
var coffee = Coffee.create('Americano', 3);
coffee.name + ', total: ' + coffee.order(3);
""")!
print(result5.toString()!) // Americano, total: 9

JavaScriptCore vs. WKWebView

In addition to JavaScriptCore that can execute JavaScript in iOS SDK, WKWebView can do the same thing.

As the name implies, WKWebView is a view, so it can display web pages directly, and it can also parse HTML and CSS. These are things that JavaScriptCore cannot do. However, it has a fatal flaw, that is it will suspend when it is not displayed on the screen. In other words, when the App is in background, or when WKWebView is not under the root view, WKWebView will be suspend just like other normal views.

So Cordova uses WKWebView, and React Native can only use JavaScriptCore (React Native has switched to the Hermes engine).

However, JavaScriptCore also has disadvantages. Except that it cannot parse HTML and CSS, it does not support Web APIs . In other words, you don’t use XMLHttpRequest and addEventListener. You must implement these yourself.

Conclusion

JavaScriptCore allows us to use Swift and JavaScript to develop iOS at the same time. Maybe someday when you have to ask for a certain function, but you can only find a library written in JavaScript, then JavaScriptCore can come in handy!

Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like
Photo by Alex Alvarez on Unsplash
Read More

Dispatch Queue Tutorial

Grand Central Dispatch (GCD) provides efficient concurrent processing so that we don’t need to directly manage multiple threads. Its dispatch queues can execute tasks serially or concurrently.
Read More