【結論】SwiftUIで作ったボタンが、MacやiPhone Simulatorでは正常に反応するのに、物理iPhone(iOS 27 beta 5)だけほとんどタップできない現象に遭遇しました。切り分けを進めた結果、アプリ側のロジックではなく、「Navigation Bar直下付近というY位置にButtonがあるときだけ、実機のタップ判定が不安定になる」可能性が高いところまで絞り込めました。現時点ではOS / SwiftUI側のbeta固有の問題を疑い、アプリ側では該当UIを約24pt下へ移動するレイアウト上の暫定回避を採用しています。
この記事でわかることは次のとおりです。
- 実機だけSwiftUIのButtonが反応しなくなった具体的な症状
- 状態管理・Navigation・端末ロールを疑って外れていった切り分けの過程
- 「画面上の位置」が原因領域だと推測するに至った実測結果
- 採用した暫定回避策と、Appleのバグと断定していない理由
注記: 本記事は iOS 27 beta 5 環境での観察記録です。「iOS 27 beta 5にはこのバグが存在する」と断定するものではなく、あくまで自分の開発環境での実測結果からの推測です。今後のbeta / RC / 正式版で挙動が変わる可能性があります。
目次
1. 発生した現象:Roadmapの過去ステップだけタップできない
現在開発中の古物商向けアプリ「古物台帳」には、査定フローの現在位置を表示するRoadmap(ステップ表示)があります。「査定 → 見積提示 → 依頼者情報 → 本人確認 → 承諾サイン → 最終確認」と進む中で、一度到達した過去のステップはRoadmap上のボタンをタップして戻れる仕様です。開発の経緯は開発1か月時点の雑記にも書いています。
ところがある時から、見積提示画面で「査定」をタップしても何も起きなくなりました。依頼者情報から見積提示へ戻ることもできません。一方で、「次へ」ボタンなど通常の査定フロー自体は正常で、最終的には取引完了まで進めます。
つまり、査定フローそのものが壊れているのではなく、Roadmapのタップだけが反応しないという状態でした。
2. 最初に疑ったのはアプリ側の状態管理だった
最初は当然、Button → autosave → Navigation → flowPath のどこかが壊れていると考えました。実際、調査の過程で別のバグを2つ発見しています。
- 変更がない保存(no-op autosave)まで、バージョンガードの判定順の問題で拒否されていた
- JSONスナップショットの日時が秒精度で保存されるため、元データの小数秒との差から「変更していないのに変更あり」と誤判定されていた
どちらも修正しましたが、この2つを直してもRoadmapのタップ不良は残りました。「別のバグを見つけて直したが、探している本当の原因ではなかった」という状態です。
そこでDEBUGビルドにトレースログを追加し、Buttonのactionから画面遷移までの経路を調べました。すると実機では、RoadmapをタップしてもButton actionのログそのものが出ていないことが分かりました。「押した後の処理」がおかしいのではなく、「押されたこと自体」が認識されていなかったのです。
3. Parent / Child差ではなく「実機かどうか」が分かれ目だった
このアプリには親機(Parent)と子機(Child)という端末ロールがあり、最初は「Parentでは動くがChildでは動かない」ように見えたため、同期状態や権限まわりを疑って調査しました。しかし同じiPhoneをParentとして動かし直しても、Roadmapは反応しませんでした。環境別に整理すると、次のようになりました。
| 環境 | Parent | Child |
|---|---|---|
| Mac | 正常 | 正常 |
| iPhone 17 Simulator | 正常 | ― |
| 物理iPhone(iOS 27 beta 5) | タップ不可 | タップ不可 |
端末ロールの差ではなく、「物理iPhoneかどうか」で結果が分かれる可能性が高くなりました。
4. Buttonは有効でframeも正常。それでもactionだけ発火しない
次にButton自体の状態を調べました。問題のRoadmapチップは progressState = completed、ロックなし、enabled で、SwiftUI上は有効なButtonです。Roadmap全体に生のタッチを検出するDEBUG用gestureを仕込むと、指のタッチ自体はRoadmap領域まで届いていることも確認できました。それでもButton actionだけが発火しません。
切り分けの材料になった観察は次のとおりです。
- SwiftUI Buttonのヒット領域対策の定番である
.contentShape(Rectangle())を追加しても改善しない - RoadmapはhorizontalなScrollView上にあるが、左右のスワイプによる横スクロールは正常に動く(透明なoverlayがタッチ全体を奪っている状態とは考えにくい)
- GeometryReaderで計測すると、Buttonのframeはラベルのpadding後・Capsule・最終frameまで約26ptで一致しており、レイアウト崩れではない
- 完全にゼロではなく、テキストの少し下のごく狭い領域で、10回に1回程度だけ稀に反応する
「Buttonのロジックが無効化されている」というより、実機上のヒットテスト/タップ認識だけがおかしいという見方に近づいていきました。
5. 調査用のViewを置いたら直った。鍵は「画面上のY位置」
原因を階層ごとに切り分けるため、DEBUGビルドでRoadmap周辺に複数の調査用(Probe)Buttonを追加しました。すると不思議なことに、これまで反応しなかった本物のRoadmapボタンまで、実機で突然正常に反応するようになりました。「診断コードを入れたらバグが消える」というかなり厄介な状態です。
そこで今度はProbeを1つずつ削除していきました。最後に残った「Roadmapの上に置いたProbe」を削除した瞬間に、再びタップできなくなりました。さらにこのProbeをButtonではなく、gestureも何も持たない単純な Text に置き換えても、Roadmapは正常に反応し続けました。
つまり重要だったのは「interactiveな要素を追加したこと」ではなく、Roadmapの上に一定の高さのViewが入り、Roadmap自体のY位置が下へ移動したことでした。
6. Roadmap以外の普通のButtonでも同じ高さで再現した
さらに決定的だったのは、Roadmapとは無関係の画面での再現です。別画面にある普通のButtonをスクロールでNavigation Bar直下付近まで持ってくると、そのButtonまでタップに反応しなくなりました。同じButtonを下へスクロールすると、普通にタップできます。
Roadmap側のButton実装が悪いのではなく、「画面上の特定のY位置」そのものに問題がある可能性が高くなりました。
また、この実機では以前から次のようなOSログが大量に出ていました。
Invalid UIScreen coordinate space conversion:
Attempting to convert rect ... which is not a valid conversion;
returning CGRectNull
アプリのProductionコードを検索しても、UIScreen や convert(_:to:) を直接使う箇所は0件でした。このログと今回のButton問題の因果関係は証明できていませんが、「実機固有の座標・ヒットテスト問題」という観察とは方向が一致しており、気になる材料ではあります。
7. 暫定回避策:Navigation Bar直下から約24pt下げる
OS内部の原因をこれ以上追い続けると開発コストが大きくなります。また、現在使っているのはiOS 27 beta 5であり、将来のbeta / RC / 正式版で挙動が変わる可能性も高いと考えました。そこで今回は、RoadmapをNavigation Bar直下の問題領域から約24pt下へ移動するというレイアウト上の応急措置を採用しました。
調査中に「Textを1つ置く程度の高さを追加すると安定して反応する」ことを確認していたため、ぎりぎりの数ptではなく少し余裕を持たせた値です。仕様上必要な24ptではなく、あくまで暫定的なworkaroundです。
逆に、次のような対処は採用しませんでした。gestureハックで直すと、OS側で修正された後に別の問題を抱え込むと考えたためです。
onTapGestureへの置き換えsimultaneousGestureの常設- UIKitのprivateなworkaroundや、見えないButtonを重ねる方法
今後のbeta / RC / 正式版では、暫定スペーシングを外した状態でNavigation Bar直下のButtonが正常にタップできるかを再確認し、OS側で解消していればこのworkaroundを縮小または削除する予定です。
8. まとめ:コードだけでなく「環境・位置・入力方法」も切り分ける
今回の調査で一番印象に残ったのは、最初「Roadmapの画面遷移処理が壊れた」と思っていた問題が、最終的に「同じButtonを画面上で少し下へ移動しただけで直る」ところまでたどり着いたことです。しかも、Roadmapとは無関係のButtonでも同じY位置で再現しました。
「SwiftUIのButtonが押せないときはcontentShapeを付ければいい」という話ではなく、MacやSimulatorでは動くのに実機だけ動かないようなケースでは、アプリ内部の状態だけでなく、次の観点まで比較すると原因領域を絞り込めることがあります。
- 実機 / Simulator の差
- ポインタ入力 / 指のタッチの差
- 画面上の位置(safe areaやNavigation Barとの距離)
- OSのbetaバージョン固有の差
今回のケースでは、「ボタンの実装」よりも「ボタンがどこに置かれていたか」の方が重要だった可能性が高い、という結論になりました。なお、別のアプリでも同様の現象を確認しています。
iOS 27 betaで同じような現象に遭遇した方や、RC・正式版での挙動を確認した方がいれば、XのDMで教えてください。正式版での再確認結果は、あらためて記事にする予定です。
コメント 0
まだコメントはありません。最初のコメントを書いてみませんか?