Home > ブログ > JavaScriptでmacOSとiPadOSを識別する

ブログ

JavaScriptでmacOSとiPadOSを識別する

2019年秋にリリース予定のiOS13ですがiPadではiOSとは別のiPadOSが使われるようになります。このiPadOS上のSafariではユーザエージェントが大きく変更されて、macOS上のSafariと見分けがつかなくなってしまいました。今回はWebアプリケーション内でiPadOSを識別するための方法を説明します。

注意: 今回はWebアプリケーション(html5/javascriptで構築したアプリ)に関する話でネイティブアプリには関係ありません。また、サーバー側での判定ではなくクライアント側(JavaScript)での判定の話になります。

2019.10.9追記

iPadの実機で確認したところ、実機ではユーザエージェント文字列に従来のiOSと同じように"iPad"の文字列が入っていました。ユーザエージェントが区別できなかったのはシミュレーターのバグだったのか?と思ったのですが、その後いろいろいじってみたところ、Safariの設定メニューに[デスクトップ用Webサイトを表示]という項目があり、これのOn/Offでユーザエージェント文字列が切り替わるようです。この設定がシミュレータだとデフォルトでOn、実機ではOffになっていたため、シミュレーターと実機でユーザエージェント文字列が異なっているように見えていただけのようです。

ユーザがPCと同じ表示をさせたいと明示的に設定した場合は、Macと同じユーザエージェントにして、表示ができるだけPCと同じになるようにするというわけですね。ただ、多くのWebサイトだとユーザエージェント文字列は参照せず、スクリーンの横幅に応じてレスポンシブ表示するケースが多いと思うので結局スマホ/タブレット用の表示になってしまいそうですが。

結局、iPadOSのユーザエージェントがmacOSと区別できなくなるのは、ユーザがデスクトップ用Webサイトを表示したいと明示的に設定した場合なので、そこで無理矢理iPadであることを検出して処理を分ける必要もないような気がします。本ページの判定処理も結局不要になりそうですが、一応、追加で調べたユーザエージェント情報を以下に追記しておきます。

==追記ここまで==

電子カタログ等のWebアプリケーションを開発しているとブラウザやプラットフォームの種類を判定して処理を分けたいケースがよくあります。

上に書いたとおり、iPadOS上のSafariはユーザエージェントがMacのSafariと同じになっており、ユーザエージェントからは判断できなくなっています(ユーザエージェント文字列の例は以下参照)。

参考: iPhone,iPad,Mac上の各種ブラウザのユーザエージェント

[Safari on iPhone + iOS13]
Mozilla/5.0 (iPhone; CPU iPhone OS 13_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Mobile/15E148 Safari/604.1

[Safari on iPad + iOS12]
Mozilla/5.0 (iPad; CPU OS 12_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1

[Safari on iPad + iPadOS13(デスクトップ用Webサイトを表示:On設定時)]
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15

[Safari on iPad + iPadOS13(デスクトップ用Webサイトを表示:Off設定時)] ※2019.10.9追記
Mozilla/5.0 (iPad; CPU OS 13_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.1 Mobile/15E148 Safari/604.1

[Safari on macOS Mojave]
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.2 Safari/605.1.15

[Chrome on macOS Mojave]
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36

[Firefox on macOS Mojave]
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0

[Safari on iPad + iPadOS]と[Safari on macOS Mojave]のユーザエージェントを比較すると、バージョン番号の細かい違いはありますが、基本的に同じ内容になっているのがわかります。

iPadはIntelじゃなくてARMでは?という気もしますがAppleとしてはiPadOSはmacOSと同じように見せたい(扱わせたい)ということなのかもしれません。

以上からユーザーエージェントによる判定は無理そうなので、別の手段を考えます。

ブラウザにはwindow.navigator.platformというオブジェクトがあり、これでプラットフォームを識別することができるかもと思いましたが、navigator.platformの値は表1のとおりになっていました。

表1 ブラウザごとのnavigator.platformの値

Platform OS Browser navigator.platform値 備考
iPhone iOS13 Safari iPhone
iPad iOS12 Safari iPad
iPad iPadOS13 Safari MacIntel デスクトップ用Webサイトを表示設定がOnの時
iPad iPadOS13 Safari iPad デスクトップ用Webサイトを表示設定がOffの時
※2019.10.9追記
Mac macOS Mojave Safari,Chrome,Firefox MacIntel

iOS12まではiPadのnavigator.platformは"iPad"でしたが、iPadOSのSafariのnavigator.platformは"MacIntel"となっており、こちらもmacOSのSafariと区別が付きません。

結局、iPadOSのSafariにあってmacOSのSafariに存在しない機能/プロパティを利用するしかなさそうだったので、探したところnavigator.standaloneが使えそうでした。

navigator.standaloneとはWebページがフルスクリーンモードで表示されているかを示すプロパティで、macOSのSafariには存在しません(undefinedになる)。

ということで以下のような判定処理にしました。

macOS上のSafariかiPadOS上のSafariか判定するJavaScriptコード例

if (navigator.platform == "MacIntel" &&
    navigator.userAgent.indexOf("Safari") != -1 &&
    navigator.userAgent.indexOf("Chrome") == -1) {
  if (navigator.standalone !== undefined) {
    // iPad OS Safari
  } else {
    // macOS Safari
  }
}

一応これでWebアプリケーション内で処理を分けることができます。

もっとスマートな方法を見つけたら更新していきます。

[補足]
以上から〜iOS12およびiPadOSを含むiPad判定は以下のようになります。

iPad判定処理

if (navigator.platform == "iPad" ||        // -iOS12
    (navigator.platform == "MacIntel" &&   // iPadOS
     navigator.userAgent.indexOf("Safari") != -1 &&
     navigator.userAgent.indexOf("Chrome") == -1 &&
     navigator.standalone !== undefined)) {
  // iPad
}

2023.10.26追記

先日リリースされたMacOSXのSafari17ではnavigator.standaloneがundefinedではなくfalseを返すようになりました。このため、上記の判定ではmacOSのSafari17もiPad OSと判定してしまいます。navigator.standalone !== undefinedではなく、document.ontouchstart !== undefinedとかで判定した方がよいでしょう。

2019.9.8 一部誤記を修正(IntelMac→MacIntel)。
2019.10.9 Safariの設定によるユーザエージェント文字列の変更について追記。
2023.10.26 macOSのSafari17でnavigator.standaloneの扱いが変わったことに関して追記。

投稿日:2019/08/20 13:56(最終更新:2023/10/26 20:29)

タグ: Webアプリ JavaScript

Top

アーカイブ

タグ

Server (28) 作業実績 (21) PHP (19) ネットワーク (17) プログラミング (15) OpenSSL (10) C (8) C++ (8) PHP関連更新作業 (8) EC-CUBE (7) Webアプリ (7) laravel (6) 書籍 (5) Nginx (5) Linux (5) AWS (4) Vue.js (4) JavaScript (4) 与太話 (4) Rust (3) Symfony (2) お知らせ (2) Golang (2) OSS (1) MySQL (1) デモ (1) CreateJS (1) Apache (1)