自作のWebアプリがなぜかiPhoneでだけ動かなかった件
知人に頼まれて、完全に趣味の範囲でWebアプリを作ったことがありました。
その際に、「PCやAndroidでは問題なく動くのに、iOS(iPhone)だけJavaScriptが効いてくれない」という問題にぶち当たりましたので、そのことについて書きたいと思います。
知人「僕のiPhoneでアプリが動かないんですけど…」
詳細は割愛しますが、どうやらWebアプリのとある部分でコードをいじってから、知人のiPhoneでうまくJavaScriptが動作していないようでした。
iOSのバージョンは16.5.1、Safariのバージョンは604.1、SafariでもChromeでも同じ症状で動かない、とのこと。
Safariに関しては、apple純正のブラウザですから、挙動の違いがあると言われてもまぁなんとなく理解はできるのですが、なぜChromeもダメなのか?
Safariはわかるけど、なんでChromeも?
いろいろ調べていると、こちらの記事を発見。
なるほど、同じブラウザをインストールしていても、OSがiOSだとレンダリングエンジン(心臓部)はすべてWebKitだから、コードの書き方によっては同じブラウザで見ていても挙動が違うということがあるらしい。
私自身はAndroidユーザーで、社内でアプリ開発をする際は職場のiPhoneを使って実機テストをしているため、プライベートではiPhoneを所有していません。
でもそうなるとエラーの再現ができないので、iPhone実機に近い形で検証をする方法を探しました。
こちら参考に、Node.jsのPlaywrightというライブラリをインストールし、使用しました。
使い勝手的なところは、またの機会に書けたらと思います。
Playwrightでデバッグできた!
なるほど、Playwrightのデバッグコンソールで確認すると、ちゃんとエラーが出てる。
ていうかstackoverflowにもおんなじ質問してる人いた。
今回のエラーの原因
起きてる事象が同じだったので、さきほどのstackoverflowの質問に回答されていた方の、サンプル検証コードから引用させていただきました。
document.write("スクリプトの先頭では `foo` の type は `" + typeof foo + "` です。<br/>")
{
document.write("ブロックの先頭では `foo` の type は `" + typeof foo + "` です。<br/><br/>")
const message = "Hello"
foo()
function foo() {
document.write("foo 内での `message` の type は `" + typeof message + "` です。<br/>")
if (typeof message == "undefined") {
document.write("foo 内では `message` は未定義です。<br/>")
} else {
document.write("foo 内での `message` の値は `" + message + "` です。<br/>")
}
}
}
つまり、関数の外で宣言した変数を、FirefoxとChromeでは参照してくれるが、Webkit系では参照できずundefinedになるというのが原因でした。
私の場合は、対策その3: 関数式を用いることで解決しました。
Safariだけ動かない事象は他にもあるっぽい
今回の私のケースとはちょっと違うのですが、おもにDateクラスを使うときや、正規表現の書き方などで思ったような挙動にならないことがあるようです。ご参考まで。