2020年4月より、iOSアプリを新規申請する際にはWKWebView対応が必要となります。
(既存アプリの場合は、2020年12月以降の更新で対応が必要。)
Cordovaでアプリを作ると、デフォルトでUIWebViewを使用する(※執筆時)ため、
今後はこの対応が必要となってきます。
この記事では、自分がリリースしたアプリでWKWebView対応した際にハマったポイントを紹介していきます。
1.CordovaでのWKWebView対応
まずは今現在主流と思われる方法を、念のため記載します。
以下プラグインを使用します。
cordova-plugin-wkwebview-engine
インストール方法は上記リンク内に載っていますが、以下コマンドを実行します。
(Cordova iOSのバージョンは4.0以上である必要があるので、古い場合は最新等にします。)
cordova plugin add cordova-plugin-wkwebview-engine
プラグインを追加したら、config.xmlに以下を追記します。
<platform name="ios"> <preference name="WKWebViewOnly" value="true" /> <feature name="CDVWKWebViewEngine"> <param name="ios-package" value="CDVWKWebViewEngine" /> </feature> <preference name="CordovaWebViewEngine" value="CDVWKWebViewEngine" /> </platform>
これで対応自体は完了です。
問題はこの後で、UIWebViewとWKWebViewの仕様のズレによって、既存のアプリの動作に影響がでることがあります。
実際自分のアプリで上記を行った所、いくつか問題が発生したので、
発生した現象と対応方法をこの後紹介していきます。
2.SQLiteでエラー
見出しの通り、まず大きな問題としてSQLite関連のエラーが発生しました。
結果から見ると、そもそもの私の実装方法がマズかった可能性がありますが、一応紹介します。
症状
アプリ起動時のSQLiteデータベースへの接続でエラー。
当然、それ以降のDB関連の処理もすべてエラー
私のアプリは主にローカルDBにデータを保存していたので、これは非常に大きな問題でした。
調べてもピンポイントで何かがヒットするわけではなかったので、
地道にいろいろ試した結果、以下の2点を対処すると上手く動きました。
対処方法
① devicereadyイベントでDB接続を行う
② cordovaのSQLiteプラグイン(cordova-sqlite-storage)を使う
以下、それぞれの詳細を説明します。
対処① devicereadyイベント
対象のアプリにおけるデータベース接続処理は以下の様になっていました。
(実際のコードではなくイメージです。Vue.jsを使用しています。)
<script> export default { name: 'App', data: function () { return { db: null } }, created () { // デバイス判定 window.setTimeout(() => { if (typeof cordova === 'undefined') { console.log('PC') this.onDeviceReady(); } else { console.log('スマートフォン') document.addEventListener('deviceready', this.onDeviceReady, false) } }, 1000) // DB初期化 this.db = window.openDatabase('test.db', '1.0', 'TEST DB', 100000) this.db.transaction(this.initDB, this.errorCB, this.successCB) }, methods: { onDeviceReady () { console.log('device ready') }, initDB: function (tx) { tx.executeSql( 'CREATE TABLE IF NOT EXISTS sample (id integer PRIMARY KEY AUTOINCREMENT, name text)' ) }, errorCB: function (tx, err) { console.log('initDB Error : ' + err) }, successCB: function () { console.log('initDB success!') } } </script>
かなり簡略化しましたが、構成的には上記のような感じです。
当初openDatabaseをどのタイミングで実行すべきかわからなかったので、
とりあえずcreatedで実装して問題が無かったのでそのままにしていました。(22行目)
さて、UIWebViewの時には上記の実装で問題が無かったのですが、WKWebView対応をしたタイミングでエラーを吐いたので、devicereadyイベント時にデータベース接続をするようにしました。
それが以下です。
<script> export default { name: 'App', data: function () { return { db: null } }, created () { console.log('--- [START]App created ---') // デバイス判定 window.setTimeout(() => { if (typeof cordova === 'undefined') { console.log('on PC') this.onDeviceReady(); } else { console.log('on スマートフォン') document.addEventListener('deviceready', this.onDeviceReady, false) } }, 1000) }, methods: { onDeviceReady () { console.log('device ready') // DB初期化 this.db = window.openDatabase('test.db', '1.0', 'TEST DB', 100000) this.db.transaction(this.initDB, this.errorCB, this.successCB) } } }
initDB等のメソッドは変わりないので割愛しています。
変わったのは、createdの中でDB初期化の処理をしていたのを、
onDeviceReadyメソッドの中で実行するように変更しました。
まず1点目はこちらになります。
対処② cordova-sqlite-storageを使う
もう一つ対応が必要だったのが、SQLite用のプラグインを使うことでした。
UIWebViewの時にも上記プラグインの存在は知っていたのですが、使わなくても動作したので使っていませんでした。
WKWebView対応でエラーを吐いたのをきっかけに、使って見たら上手く行ったという経緯です。
具体的な手順ですが、まずは以下でプラグインを追加します。
cordova plugin add cordova-sqlite-storage
そして、openDatabaseする際にこのプラグインを使うように変更します。
対象箇所はonDeviceReadyメソッド内で、以下の様に変更しました。
onDeviceReady () { console.log('device ready') // DB初期化 this.db = window.sqlitePlugin ? window.sqlitePlugin.openDatabase({name: 'test.db', location: 'default'}) : window.openDatabase('test.db', '1.0', 'TEST DB', 100000) this.db.transaction(this.initDB, this.errorCB, this.successCB) }
2点目としてこちらを変更することで、WKWebViewに変更後もDB接続ができるようになりました。
どちらか片方だけで試したときはダメそうでしたので、どうやらこの2点両方が必要そうという結論でまとめています。
(原因を詳しく調査したわけではないので、帰納的な結論です。)
※余談ですが、ESLintによって文末のセミコロン禁止ルール(no-extra-semi)がかかっているので、
やや見辛いかもしれません。スミマセン。。
結果から見ると今回のケースは私の元々の実装方法がマズかった可能性が高いのですが、
備忘録として残しておきます。
この他にもWkWebView対応でハマった点がいくつかありますので、
次回以降の記事で紹介したいと思います。
SQLが学べる 関連連載リンク
データベースの基礎が学べるSQL基礎講座
SQL基礎 連載
練習問題を通じてSQL理解度アップの人気連載!
SQL練習問題集