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練習問題集