はじめに
1. JavaScriptCore
2. 基本的な使い方
3. 変数の扱い方
4. APIを定義する
5. 変数を扱うときの注意
6. 座標や範囲を表す型の扱い
7. 例外処理を使う
8. SwiftでPromiseを使う
9. コードを書きやすくする
10. Promiseを使いやすくする
あとがき
キーワード索引
逆引き索引
iOSアプリやmacOSアプリの開発では、標準で「JavaScriptCoreフレームワーク」というJavaScript実行環境を利用できます。
これを使うと、JavaScriptコードを文字列として実行するだけでなく、SwiftのネイティブなコードとJavaScriptのコードとを密接に連携して、インスタンスを介して互いのデータにアクセスするなど、自由度の高いプログラミングが可能になります。
本書では、そんなJavaScriptCoreフレームワークをSwiftで扱う方法を、順を追って見ていきます。iOS アプリやmacOSアプリでネイティブなJavaScriptプログラミングを始めてみましょう。
・Swift 5.2.2
・Xcode 11.4.1 (11E503a)
本書の内容は、情報提供のみを目的としております。正確性には留意しておりますが、正確性を保証するものではありません。本書の記載内容に基づく一切の結果について、筆者は一切の責任を負いません。
本書に記載されている会社名、製品名などは、一般に各社の登録商標または商標、商品名です。会社名、製品名については、本文中では©︎、®︎、™️マークなどは表示していません。
本書籍は、技術系同人誌即売会「技術書典」などで頒布されたものを底本としています。
JavaScriptCoreとは何者なのか、まずはそんなあたりから見ていきます。さらりと読んでJavaScriptCoreと、それを取り巻くJavaScriptのイメージを膨らませてみましょう。
JavaScriptCoreは、JavaScriptをアプリ内で実行可能にするフレームワークです。iOS 7.0以上、macOS 10.5以上、tvOS 9.0以上、Mac Catalyst 13.0以上で使えます。
JavaScriptCoreは、実際にAppleのHTMLレンダリングエンジンWebKitのJavaScript実行エンジンとして使用され、そのWebKitはApple標準のWebブラウザーSafariで使われているそうです。そんな本格的なJavaScript実行エンジンを自作アプリに組み込んで簡単に使えることが、JavaScriptCoreの大きな醍醐味と言えます。
JavaScriptCoreを使えば、アプリ内部にJavaScript仮想マシンのインスタンスを作成し、そこで任意のJavaScriptコードを実行できるようになります。コードは文字列で与えれば良いので、実行したいJavaScriptコードをあらかじめアプリ内に組み込んでおくだけでなく、ランタイムでJavaScriptコードを作って実行することも可能です。
Objective-CやSwiftで作ったネイティブなクラスをJavaScript仮想マシンにエクスポートして、JavaScriptコードから直接操作することもできます。インスタンスはネイティブ環境とJavaScript環境とで相互に利用できます。そのため、単にJavaScriptコードを実行して結果を得るだけでなく、JavaScriptでネイティブコードを制御することも可能になります。
そんなJavaScriptCoreですが、できることの幅が広く強力すぎて、どんなことに使えそうかが想像しにくいところです。そこで、どんな場面で利用できそうか少し考えてみることにします。
まず、思いつくのが「外部からテキストデータをダウンロードして、アプリの動作を変更したい」場面です。たとえばWebサイトをスクレイピングしてデータを取得するアプリで、参照先のWebサイトの仕様が変わったとします。このとき、アプリをアップデートすることなく迅速に対応したい場合に、有意義に活用できる仕組みのように思います。
また、アプリ利用者が「カスタムスクリプトを書いて、動作をカスタマイズできる環境」を簡単に提供できます。SwiftネイティブコードをJavaScriptで直接制御できる1ため、必要なAPIさえ用意してあげれば、それだけでJavaScriptからのアプリの制御が可能になります。
JavaScriptを書ける人はたくさんいると思うので、それをカスタムスクリプト用の言語として提供できるのは嬉しいところです。
ところで、今回のテーマであるJavaScriptCoreで実行可能なプログラム言語JavaScriptとはどんなものか、簡単に見ておきましょう。
個人的にJavaScriptは、主にWebブラウザーでHTMLを自由自在に扱うための言語という印象があります。そもそもは1995年頃からDynamic HTMLを実現するためのスクリプト言語として登場しました。それから今日までずっと、Webの世界を引率してきたと言っても良いかもしれません。
そんなJavaScriptですが、コードの雰囲気はイマドキの言語に引けを取らないくらいスマートな記述ができるように思います。テキストエディターでサラサラと書いて、それをコンパイル作業をしなくてもすぐに実行できる手軽さも魅力のひとつと言えそうです。
var outputItems = new Array();
var lines = clip.content.split('\n');
var expression = /^\s*([^:]*)\s*:\s*(.*)\s*$/;
for (var index in lines)
{
var line = lines[index];
var itemContent;
if (line.match(expression))
{
itemContent = RegExp.$2;
}
else
{
itemContent = line.trim();
}
outputItems.push(escapeHtml(itemContent));
}
JavaScriptの言語仕様は、ECMAScriptとして標準化が図られています。策定された仕様のどこまで対応しているかは、実行環境によって違ってきます。そんな対応状況は、ECMAScript互換テーブル2のサイトで確認できました。
たとえば2016年12月に確認したときには、Safari 10が搭載されたmacOS 10.12 SierraでECMAScript 6に完全対応しているようです。それに対してSafari 9では、ECMAScript 6には50%ほどしか対応していないものの、ECMAScript 5についてはほとんどが使えるようでした。
そして2020年2月の時点でのSafariのECMAScript 6対応状況ですが、Safari 13が搭載されたmacOS 10.15 Catalinaでは、下がって99%の対応状況になっていました。それ以降のECMAScript 2016+ 対応状況としては、Safari 13で80%の対応状況です。そのひとつ前のSafari 12.1では75%の対応状況になっているようです。
また、JavaScriptCoreを使う場合は、実行時のOSのバージョンによって使える機能も変わってきます。最新のJavaScript機能を使いたいときには、どのOSでどのバージョンJavaScriptCoreが使えるのかをまず把握して、適切な環境だけで動作するように、アプリのDeployment Targetを設定する必要がありそうです。
JavaScriptCoreは、強力で魅力的なフレームワークになっていると思います。可能性は無限大、そんなJavaScriptCoreを使ってみませんか?
以降では、Swiftを使ってJavaScriptCoreを扱う方法を綴っていきます。それを見れば、その強力さとは裏腹に、シンプルな記述で使えることを知ってもらえるかと思います。ぜひ真似して使ってみて、そこから新しいプログラミングの世界を拓くきっかけにしてもらえたら幸いです。
JavaScriptCoreは、Playgroundで実行できるようになっています。MacにXcode3を入れればすぐに試せるので、ぜひ遊んでみてください。ちょっとしたJavaScriptコードの動作を試したいときにも便利です。
PlaygroundでJavaScriptCoreを使う際、気をつけておきたい点があります。SwiftのクラスをJavaScript側で使いたい場面では、少なくともJavaScriptにエクスポートするAPIを記載するプロトコルの定義は、即時に実行されるエディターではなく、そのサブフォルダーSources内のSwiftファイルに書く必要があります。これについては <4.8> で紹介します。