まえがき
CordovaやOnsenUIなどフレームワーク等を大量に使っていると、問題の根源がどこにあるか分かりづらい。
それが原因で丸2日ぐらい格闘したのち、あっけなく根本的に(正攻法でとは言っていない)解決させたので紹介します。
結論
とりあえず、結論から言うと以下の3つのプラグインを導入しましょう。
(解決させるのは一番上のcordova-plugin-wkwebview-engine
ですが、導入前に使えていた機能が一部使えなくなってしまったので、残りの2つで補填しています)
https://github.com/apache/cordova-plugin-wkwebview-engine
https://github.com/oracle/cordova-plugin-wkwebview-file-xhr
https://github.com/apache/cordova-plugin-inappbrowser
解説
この先非常に長文です。解決すればそれで満足な方は、読まないことをおすすめします
経緯などを解説します。そのほうが検索にヒットしやすくなって、沢山の人の参考になるかなと・・・(メタい)
問題発生
OnsenUIとCordovaで開発をしていたのですが、ons-navigator
のpushPage
で画面遷移を行うと、iOS上でだけ稀にちらつき(厳密には遷移完了後に前画面の残骸が一瞬表示される)が発生しました。
あらゆる方向から原因を探りましたが、なかなか諸悪の根源にたどり着けませんでした。
OnsenUIのバグなのか
最初は「OnsenUI ちらつき iOS」などで調べると、以下のようなサイトがヒットしました。
https://ja.stackoverflow.com/questions/11351
https://stackoverflow.com/questions/31286320
https://github.com/OnsenUI/OnsenUI/issues/384
ons-pageがネストしているのではという指摘
調べたところ、ons-navigator
>ons-page
>ons-tabbar
>ons-tab
>ons-navigator
>ons-page
という構造になっていたので、ネストしているっちゃネストしている。
ただ、実現したい仕様的にons-navigatorを1階層にするのは難しいと判断したため、特に試すことなく終了。
ons-tabbarがどうこうという記事なども見つけましたが、回答(解決策)がなかったり試してもうまく行かなかったり途方に暮れていました。
ちなみにこんな書き込みも見つけました。
https://twitter.com/onsen_ui_ja/status/874579153839726592
Web業界ではブラウザ間の差異まで吸収するのがフレームワークの役目のようなので、OnsenUIのバグと位置づけられても仕方ない気もしますが、その常識に物申したい私だったりします・・・
CSSで無理やり治す
結局、CordovaのせいなのかOnsenUIのせいなのかiOSのせいなのか自分の書いたコードのせいなのか、なにもわからずいろいろ調べまくりました。
結果出てきた解決策の殆どがCSSで治すworkaroundでした。
https://stackoverflow.com/questions/3461441
https://stackoverflow.com/questions/2946748
https://stackoverflow.com/questions/14723514
https://stackoverflow.com/questions/17747239
https://yumeirodesign.jp/blog/201312/csstransforms_fixed.html
色々な策が見つかりましたが、まず一番多かったのが-webkit-backface-visibility: hidden;
で治るという記事。色んな要素に適用してみましたが、どれも駄目
次いでmeta[name=viewport]
にuser-scalable=no
を追加するという記事。これは既に追加済みでした(=駄目)。
他にもjQueryのdefaultTransaction(defaultTransition?)を無効化するなどいろいろな方法が挙がりましたが、全部撃沈
iOSのシステム側の問題
色々調べてると、iOS側のバグ(OnsenUI等JavaScript,CSS,HTMLサイドのバグではない)という記事がちょっとずつ出てきました。
そして大ヒントになったのがこの質問。
https://teratail.com/questions/105472
(ちなみに-webkit-overflow-scrolling: auto !important;
を試したりOnsenUIのバージョンを確認したり(2.10.1でした)もしましたが駄目でした。)
UIWebViewのバグと書いてあって、「ほー、OS側なのか。Cordovaで開発してるわけだし、CSS,JS側でできるworkaroundないかなー」と思い(散々撃沈したけど)、OnsenUIの書き換え(pushPageのソース書き換えて、CSSや属性の書き換えタイミングを遅延させればどうにかなるのではと思い)も覚悟しましたが、そういえばUIWebViewってどんな仕様になってるんやろと、ふと調べてみました。(ここに至るのには「アプリカン」という別サービスで検証してみた経緯もあり、あちらだと一切チラツキは再現せず、公式ページに「Webview刷新」などという謳い文句があったこともあり・・・)
すると飛び込んできたのが「Deprecated」の文字。「お?」と思い検索結果を見ているとこんな記事が・・・
https://qiita.com/ShingoFukuyama/items/01a9cdf24090931b4ef3
「なるほど、UIWebView
ってあんまりよろしくないのね」ぐらいに思いつつ、Chromeが新しいWKWebView
を採用しているという言葉に謎の期待を持ち、CordovaでWKWebView
が使えないか調べてみました。
(記事を書きながらふと思えば、当時Cordovaが標準でWKWebViewを使っている可能性は疑いませんでしたね・・・)
プラグインの導入
そうしたらありましたよ、Cordovaプラグイン。
https://github.com/apache/cordova-plugin-wkwebview-engine
これは入れてみるしかない!と思い、早速インストールしてconfig.xmlも指示通り書き換えて起動
結果から言うと、別画面のtemplateファイルを読み込む際に「Cross origin requests are only supported for HTTP」とかで怒られて駄目でした。
https://stackoverflow.com/questions/46996292
調べるとこんな記事がヒットし、「プラグイン自体書き換えないと駄目かなー」などと思っていたらありました、プラグイン。
https://github.com/oracle/cordova-plugin-wkwebview-file-xhr
(最初に見つけたのは https://github.com/TheMattRay/cordova-plugin-wkwebviewxhrfix でしたが、最終更新が比較的前だったり、制作者が個人でURL直指定じゃないとインストールできないなど、もう少し良いものがないかと思い探した結果、上記のプラグインにたどり着きました)
入れて実行してみると、きちんとファイルも読み込め、チラツキも見事になくなりました。
動いたー、けど一部・・・
よしよしと思っていたのですが、ある部分でwindow.open(hogehoge, '_system')
を使用しており、正しく動作してくれませんでした。
そして色々調べて見つけたのがこれ(本題からそれつつあるので適度に簡潔に)
https://github.com/apache/cordova-plugin-inappbrowser
(最初に見つけたのは https://github.com/dpa99c/cordova-plugin-inappbrowser-wkwebview でしたが、最終更新が(中略)たどり着きました。採用したほうはWKWebView対応を謳っていませんでしたが、結論から言うと問題なく動作しました)
括弧内でも述べてますが、こちらも導入しただけですんなり動作してくれました。
(window.open
は非推奨だからcordova.InAppBrowser.open
を使ってねとREADMEに書いてありましたが、動いちゃったので今の所変えてないです)
あとがき
だいぶ長くなりましたが、できるだけ手順を記して、どの時点でハマった人でもこの記事に辿り着けるようにしたかったというのが本音です。(さっき言ったことの言い換え)
正直「英語アレルギーないからすぐに答え見つかるやろー」とか舐めてかかっていたのですが、めっちゃハマりました・・・(この記事を英語化する予定はありません)
天下のAppleさんが諸悪の根源だなんてありえない・・・という盲信もありました。
というよりWebブラウザなんて、Appleに限らずベンダーによってCSSやらJavaScriptの挙動が違うとかとても良くある話なので、JavaScriptやらCSSで醜い分岐を組んでやるしかないんだろうなーという思いのほうが強かったかもしれません。
なんだったら今や新機能だって、ほとんどの主要なブラウザが同等の実装をしてるのにベンダープレフィックスって要るのか?とか思ってます。
試験的な機能を隔離したい(簡単に使えなくしたい)気持ちはわかりますが、それはブラウザごとに記法を変えるべき理由にはならないと思うんです。
あとがきもチラ裏が入ったり長くなってしまいましたが、このへんで。
最後まで読んでいただきありがとうございました。
gsaCsYLrgsWDbINDg2WDQoN1g0GDdoOKgsiC54KxgvGCyIvqmEqCyIKpgsGCvYLGjnaCooLcgreCtYFBg26DQ4N1g4qDYoNog0GDdoOKguKC34LcgrmC8YFIgUiBSA==