[DevTools] 入門講座 #04:iPhone SafariをWindowsでデバッグする手順

1. Storage Estimate API は使えない?

Webアプリ開発において、ストレージ使用量を可視化する navigator.storage.estimate() は非常に便利なAPIです。 IndexedDBの容量管理や、ZIPアセットの登録状況の可視化に使おうとしたのですが──

✅ Safariだけnullになる…?

Chromeでは以下のように正常に取得できます:

const { quota, usage } = await navigator.storage.estimate();

しかし、iPhone Safariでは このAPIが null を返すか、あるいは中身が空のオブジェクトで返ってくる。

const storage = await navigator.storage.estimate();
console.log(storage); // → null または { usage: undefined, quota: undefined }

これにより、下記のようなコードで即エラーになります:

const totalStorage = formatBytes(storage.quota); // ← TypeError: null is not an object

❗ 見落とされやすい原因

一見 navigator.storagenavigator.storage.estimate も存在するように見えるため、 「使える」と誤認してしまうのが落とし穴です。

"storage" in navigator // true
"estimate" in navigator.storage // true
await navigator.storage.estimate() // null!!

Safariは仕様上、APIの存在は名乗るが実装はしていないという、厄介な状態になります。


🛡️ 対策:防御的な関数を設計する

以下のように nullundefined を受け入れる形に書き直すことで、 Safariやその他一部環境でも安全に動作するようになります:

async function getStorageEstimate() {
  if ("storage" in navigator && "estimate" in navigator.storage) {
    try {
      const estimate = await navigator.storage.estimate();
      if (!estimate) throw new Error("estimate() returned null");

      const used = estimate.usage || 0;
      const quota = estimate.quota || 0;
      const percent = ((used / quota) * 100).toFixed(2);

      return { used, quota, percent };
    } catch (e) {
      console.warn("Storage Estimate API に失敗:", e);
      return { used: 0, quota: 0, percent: 0 };
    }
  } else {
    console.warn("このブラウザは Storage Estimate API をサポートしていません");
    return { used: 0, quota: 0, percent: 0 };
  }
}

🔍 結論

  • Safariでは navigator.storage.estimate()名乗るだけで実装されていない
  • nullが返ってくる前提で設計する必要がある
  • バグではなく「仕様」だが、見落としやすい落とし穴

2. iPhone Safariで検索バーが消えない理由とその挙動を検証してみた

WebアプリをiPhone Safariで動かすと、**画面上部に常に表示される「検索バー(アドレスバー)」**に悩まされることがあります。 特にゲームやアセット管理など「全画面表示に近いUI」を目指す場面では、 このバーが常に出たままになるだけで没入感や操作性が大きく損なわれてしまいます。


✅ 通常のブラウザでは…

ChromeやAndroid系ブラウザでは、

  • 100vh 指定で高さを制御できる
  • スクロールでアドレスバーが隠れる
  • overflow: hidden などでスクロールを抑止できる

といった制御が可能です。


❗ しかし、Safariは違う

iPhone Safari では以下のような独自仕様があります:

条件 アドレスバーの挙動
ページにスクロール可能な要素がある アドレスバーが表示されたままになる
overflow-x: auto のみでも発動 横スクロールだけでも「スクロール可能」と判定される
DOM操作で要素が変動する Safariが再描画タイミングでバーを復活させる

特に今回問題となったのは、アセット一覧の横スクロール用に設定していた以下のCSSです:

#asset-body {
  overflow-x: auto;
}

この1行があるだけで、iOS Safariは 「ページがスクロール可能な状態」と認識し、 100%の確率でアドレスバーを表示してしまうようになっていました。


🔍 なぜこのような仕様なのか?

Appleからの公式な説明はありませんが、検証結果から考えられる理由は以下のとおりです:

  • iOSは画面サイズが限られており、常に「スクロール余地=ユーザー操作の可能性」とみなす
  • AppleはセキュリティやUX方針の観点から、スクロールがあるページはバーを隠さない方が安全と判断している可能性
  • ユーザーが「いつでも戻れる」ように、アドレスバーを極力保持する設計

🛠️ 検証してみたCSS対策

html, body {
  height: 100%;
  overflow: hidden;
  margin: 0;
  padding: 0;
  touch-action: none;
  overscroll-behavior: none;
}

これにより、画面全体の上下スクロールは抑止できましたが、 内部要素に overflow-x: auto があるだけで再びアドレスバーが出現。


🎯 結論と方針

  • Safariでは「アドレスバーを確実に消す」ことはできない
  • 消すことを目指すより、「出ても問題のないUIを作る」ことを目指すべき
  • overflow-x: auto をやめて、JSで translateX() などによるスワイプ風スライドに置き換えるのも有効

💡 補足:「ツールバーを非表示」手動オプションもある

Safariの「ページ設定」メニューには **「ツールバーを非表示」**という手動オプションも存在し、これを使うとかなり画面が広くなります。 ただし、ユーザー操作が必要なためアプリ側で制御することはできません。


🔚 まとめ

  • アドレスバーは「出るのがデフォルト」である
  • 出さないことではなく「出ても困らないレイアウト設計」が鍵
  • iOS Safari固有の挙動を理解して、過度なCSS調整に振り回されないことが重要

3. 今回の学びと今後に活かすポイント

今回の検証を通して、ただ「動かない理由を突き止める」だけではなく、 iPhone Safari というブラウザが持つ独自の性質や“前提の違い”に気づくことができました。

この章では、開発の中で得た気づきを振り返りながら、 今後のモバイルWebアプリ開発にどう活かしていけるかをまとめます。


✅ Safariでは“存在しても使えないAPI”がある

  • navigator.storage.estimate() は Safariでも存在はするが、値がnullで返ってくる
  • 「APIがあるかどうか」ではなく、「実際に返ってくる値を使えるか」まで検証が必要
  • 例外を吸収できる防御的な関数設計が必須

✅ iOS Safariの“見えないルール”に注意

  • 横スクロール可能な要素があるだけで、アドレスバーの常時表示が発生
  • 全画面表示を目指す場合、「スクロールをなくす」ではなく 「出ても崩れないレイアウトを構築する」発想に切り替える必要がある
  • モバイルUI設計では「OS側の仕様」を考慮に入れないとバグに見える挙動が頻発する

🧠 「原因を知る」ことで不安が消える

今回もっとも大きな収穫は、 「仕様を知らなかったがゆえに、不具合に見えていた現象」の正体を突き止めたことでした。

  • 原因がわからない間は、あらゆるところに不安と疑心が生まれる
  • 原因を把握すれば、それが**「バグではなく、そういう仕様だった」**と受け入れられる
  • 「知らなかっただけ」だった問題を、一つひとつ“知っている”に変えていくことが、最も確実な開発スキルの獲得法

🚀 今後の活かし方

分野 具体的な行動
モバイル対応 SafariやiOS向けの検証環境を早期に整える
API設計 使用前にnullチェックやフォールバック処理を組み込む
UI設計 「想定外のUI変化」があっても崩れにくい柔軟なCSS構造を設計する
記録と継承 このような検証結果は即記事にして残すのが効果的(未来の自分のために)

🧭 最後に

今回の内容は一見すると「細かいSafari対策」に見えるかもしれません。 しかしその裏には、

  • 「あえてiPhone実機をデバッグする環境を整えたこと」
  • 「一見関係ないバグの裏に仕様の壁があったこと」
  • 「見えない理由を見えるようにしていったこと」

が積み重なっています。

これはただの技術ノートではなく、Webアプリを“本気で届けよう”とする人の記録なのです。


最後に

iPhoneのデバッグ環境構築に手間り、かなり時間がかかり、その後、問題の動かないデバック作業に挑んだのですが、デバッグする箇所は、「Storage Estimate API 」これだけでした。

もっとたくさん直す箇所があると思ってたのに、拍子抜けするほど少なかったです。

ただ、今後同様の問題が出てくると思うので、環境構築及び、ほぼ使っていなかった、Mac環境のアップデート、更に、過去に作ったiPhoneアプリを実機で動かすところまでテストできたのは良かったです。

当時は、SwiftやJavaで、スマホアプリを開発していましたが、ちょっとしたアプリであれば、JavaScriptで書けば、両方で動いてしまうし、WEB、Linux環境でも動くというのは、JavaScriptの大きな強みだと思います。

別で書いた記事も含め、参考になれば幸いです。