この記事では、実際の問い合わせから再現、A/Bテスト、修正後の確認までを記録します。コードの変更と手動操作の結果を分け、確認できた範囲を示します。
発生した不具合:余白では動くが、セル上では選択される
2026年10月3日、PhraseBoardの利用者から「カテゴリ内の下に隠れた文章を選択できない」と問い合わせがありました。追加の説明では、余白を指でドラッグすると一覧が動く一方、定型文セル上からスクロールしようとすると、意図しない定型文が選択されるとのことでした。
iPad Pro(第2世代、12.9インチ)/横向き/ハードウェアキーボード接続/複数行の定型文2件。OSは後の返信でiPadOS 17.7.11と申告されました。端末から直接取得した値ではなく、利用者からの申告です。
つまり、ScrollView全体が動かなかったわけではありません。余白からはスクロールできても、セル上で始めたドラッグが定型文の選択になってしまい、一覧を操作しにくい状態でした。
開発側で不具合を再現
開発者は、App Store配信中のPhraseBoard v1.2.1をiPad Pro 12.9インチ(第2世代)・iOS 17.2 Simulator・横向きで動かし、スクロールできない症状を確認したと当時のログに記録しています。開発者自身のM4 iPad Air 11インチでは元の実装で再現しなかったという報告もありましたが、その端末のOSバージョンは記録上確認できません。端末世代とOSのどちらが挙動差に関係したかは、この比較だけでは決められません。
修正前のSwiftUIコード
v1.2.1の定型文一覧はScrollView → LazyVGrid → Buttonで構成されていました。Buttonの通常アクションは定型文を入力し、セルに付けたLongPressGestureは長押しコピーを呼び出します。長押し後にButtonの入力処理が続かないよう、suppressPhraseTapも使われていました。
以下は実ソースからの抜粋です。セル表示のVStackとButtonStyleは一部省略しています。
// v1.2.1の定型文セルから抜粋
Button {
if suppressPhraseTap {
suppressPhraseTap = false
return
}
playSelectionFeedback()
onSelectPhrase(phrase)
} label: {
// セルのVStackを配置
}
.buttonStyle(
KeyboardPressStyle(
normalBackground: regularKeyColor,
pressedBackground: pressedRegularKeyColor,
cornerRadius: keyCornerRadius
)
)
.simultaneousGesture(
LongPressGesture(minimumDuration: 0.5)
.onEnded { _ in
suppressPhraseTap = true
onLongPressPhrase(phrase)
}
)このコード抜粋は、v1.2.1のapp/PhraseKeyboardExtension/Views/KeyboardRootView.swift(定型文一覧付近)に基づいています。独自のDragGestureやhighPriorityGestureを追加した説明ではありません。
LongPressGestureを外したA/Bテスト
原因を切り分けるため、開発当時の診断版では定型文セルの.simultaneousGesture(LongPressGesture(minimumDuration: 0.5))だけを一時的に無効化したと報告されています。Codexの作業報告では、Buttonと通常タップ処理、ScrollView、レイアウト、suppressPhraseTapは変更していません。診断版では長押しコピーは動きません。
| 条件 | 定型文セル上のスクロール | 変更内容 |
|---|---|---|
| A:v1.2.1相当 | 不可と開発者が報告 | ButtonにLongPressGestureあり |
| B:診断版 | 可能になったと開発者が報告 | LongPressGesture modifierだけ一時無効化 |
比較対象はiPad Pro 12.9インチ(第2世代)・iOS 17.2 Simulator・横向きで、同じ定型文データを使うよう依頼されていました。その後、開発者は診断版で「スクロール可能になった」と報告しています。
今回のiOS 17.2 Simulator環境では、LongPressGestureを含むセル実装がスクロール阻害の直接条件だったと判断できます。ただし、このA/BだけではSwiftUI内部の具体的な認識機構や、他の端末・OSで同じ現象が起きる範囲までは証明できません。A/Bで確認できたのは診断版でのスクロール改善までです。恒久修正後は実機とSimulatorでスクロールやコピーを確認したとの報告がありますが、Menuの個別操作や各環境の詳細までは記録に明記されていません。
初期のDragGesture案で起きた回帰
初期案ではセル側にDragGesture(minimumDistance: 0)を追加して、タップと移動を判定しようとしました。しかし、元の実装でスクロールできていたM4 iPad Airでも、追加後はセル上からスクロールできなくなりました。追加したGestureと関連処理を撤回すると、セル上と余白の両方でスクロールが復帰したと開発者が確認しています。
この試行はLongPressGestureのA/Bとは別です。セルへ独自DragGestureを加えることが、親のScrollViewを必ず助けるわけではないと分かり、採用案からは外しました。
採用した修正方法:iOS 17はMenu + primaryAction
v1.2.2では、OSによってセル操作を分けました。iOS 17ではMenuの通常操作にprimaryActionを割り当て、タップで入力、長押しでメニューを表示し、メニュー内の「コピー」で既存のコピー処理を呼びます。iOS 18以降は従来のButton+LongPressGestureを維持します。長押しコピーを取り除くのではなく、iOS 17では操作方法を変更した形です。
| OS経路 | 通常タップ | 長押し | コピー |
|---|---|---|---|
| iOS 17 | 定型文を入力 | Menuを表示 | Menuの「コピー」を選択 |
| iOS 18以降 | 定型文を入力 | 従来どおり長押し | 長押しで即コピー |
iOS 17経路の実ソースからの抜粋です(OS分岐や周辺ヘルパーは省略)。
case .menu:
Menu {
Button {
copyPhrase(phrase)
} label: {
Label("コピー", systemImage: "doc.on.doc")
}
} label: {
phraseCellLabel(phrase)
} primaryAction: {
playSelectionFeedback()
onSelectPhrase(phrase)
}
.buttonStyle(phraseCellButtonStyle)OS分岐は#available(iOS 18.0, *)で判定し、iOS 18以降を従来Gesture経路、iOS 17をMenu経路にしています。ScrollViewと基本レイアウトは維持されています。コードはv1.2.2のapp/PhraseKeyboardExtension/Views/KeyboardRootView.swiftおよびapp/PhraseKeyboardExtension/Actions/KeyboardPhraseInserter.swiftに基づいています。
MenuはPhraseBoardで採用した実装上の判断です。同様の症状すべてにMenuが適切だという意味ではなく、実際の画面と操作で確かめて選ぶ必要があります。
v1.2.2の利用者向けアップデート内容はPhraseBoard v1.2.2のアップデート記事にも掲載されています。
修正後のテストと動作確認
当時の作業報告では、swift testは109件すべて成功し、iOS 17.2 Simulator向けDebug BuildとRelease Buildも成功しました。これはビルドと自動テストの結果であり、それ自体がジェスチャー操作の確認を示すものではありません。
その後、開発者は「スクロールやコピーに関しては完了で良さそう。実機確認とシミュレーターで確認しました」と報告しています。修正後の手動確認があったことは確認できますが、この発言には実機の機種・OS、Simulatorの条件、スクロール・タップ・Menu・コピー各操作の個別結果は列挙されていません。そのため、すべての端末・操作が個別にPASSしたという表にはしていません。
同様の問題を調べるときの確認ポイント
今回の調査で有効だったのは、スクロールコンテナ全体の問題と、子セル上でだけ起きる問題を分けて見たことです。似た症状では、次の順で確認すると原因を絞りやすくなります。
- 余白から始めたドラッグと、セル上から始めたドラッグの結果を比べる。
- セルがButtonか、どのGesture modifierが付いているかを確認する。
- 端末、OS、向き、入力方法、表示データをそろえて比較する。
- 診断では一度に一つの処理だけを変え、A/Bの差を見る。
- 修正後はスクロールだけでなく、通常タップやコピーなど既存操作も手動で確認する。
この手順は切り分けの観点です。今回のMenu実装を一般解として勧めるものではありません。
まとめ
- 問題はScrollView全体ではなく、主に定型文セル上でのスクロール操作として報告されました。
- 開発当時、iOS 17.2 Simulatorでv1.2.1の症状が再現したと記録されています。
- LongPressGesture modifierだけを無効化した診断版で、セル上のスクロールが可能になったとの報告がありました。
- v1.2.2ではiOS 17にMenu+primaryAction、iOS 18以降に従来の長押し処理を採用しました。
- 修正後も実機とSimulatorで確認したとの報告がありますが、個別の端末・操作結果は記録にありません。
今回の事例では、具体的な端末・OSとセル実装をそろえたA/Bテストが原因の切り分けに役立ちました。ジェスチャーの不具合は環境を限定して検証し、その範囲を明示することが大切です。
コメント 0
まだコメントはありません。最初のコメントを書いてみませんか?