Xcode 26 + UIDesignRequiresCompatibility環境でUISegmentedControlのタップ位置がズレる問題

Xcode 26 + UIDesignRequiresCompatibility環境でUISegmentedControlのタップ位置がズレる問題

2026.01.22

現在、開発環境を Xcode 26へアップデートするための検証をおこなっている。Liquid Glass対応については議論中で、一旦UIDesignRequiresCompatibilityをYES(リキッドグラス無効化)にした状態でリリースすることにした。

その過程で、UISegmentedControl のタップ位置が正しく認識されない不具合を発見した。本記事では、この不具合の詳細と再現条件について報告する。

不具合の概要

未選択状態の UISegmentedControl をタップした際、タップした位置と実際に選択されるセグメントがズレる現象が発生する。

具体的には、右端のセグメント(index: 3)をタップしたにもかかわらず、左端のセグメント(index: 0)が選択されてしまう。

スクリーンショット 2026-01-22 14.42.30

検証環境

  • MacBook Pro (16インチ, 2023), Apple M2 Pro
  • macOS 15.7.3
  • Xcode 26.1.1、26.2
  • iOS 18.5、26.2
  • iPhone 16 Pro Simulator、実機

発生条件

この不具合は、以下のすべての条件が揃った場合に発生する。

  1. Xcode 26.x でビルドしていること
  2. UIDesignRequiresCompatibilityYES に設定していること
  3. UISegmentedControl を Auto Layout で左寄せで配置していること
  4. UISegmentedControl の表示項目を動的に変化させていること

特に4番目の条件が重要である。Storyboard上で静的にセグメントを設定した場合は問題なく動作するが、コードから insertSegment(withTitle:at:animated:) を使って動的にセグメントを追加した場合にのみ発生する。

再現手順

1. プロジェクトの準備

最小限の再現プロジェクトを用意した。

https://github.com/CH3COOH/Samples/tree/master/SampleSelectSegmentedControl

2. CustomSegmentedControl の実装

UISegmentedControl を継承し、動的にセグメントを設定するメソッドを追加する。

import UIKit

class CustomSegmentedControl: UISegmentedControl {

    func setSegments(titles: [String]) {
        removeAllSegments()
        titles.forEach { title in
            insertSegment(
                withTitle: title,
                at: numberOfSegments,
                animated: false
            )
        }
    }
}

3. ViewController の実装

Storyboard上に2つの UISegmentedControl を配置し、IBOutletで接続する。

import UIKit

class ViewController: UIViewController {

    // 上のSegmentedControl(標準)
    @IBOutlet weak var topSegmentedControl: UISegmentedControl!

    // 下のSegmentedControl(カスタム)
    @IBOutlet weak var bottomSegmentedControl: CustomSegmentedControl!

    override func viewDidLoad() {
        super.viewDidLoad()

        // 未選択状態に設定
        topSegmentedControl.selectedSegmentIndex = UISegmentedControl.noSegment

        // カスタムメソッドでセグメントを設定
        bottomSegmentedControl.setSegments(
            titles: ["Item A", "Item B", "Item C", "Item D"]
        )
        bottomSegmentedControl.selectedSegmentIndex = UISegmentedControl.noSegment
    }
}

4. Info.plist の設定

UIDesignRequiresCompatibilityYES に設定する。

<key>UIDesignRequiresCompatibility</key>
<true/>

5. 再現確認

  1. アプリを起動
  2. 下の CustomSegmentedControl の右端("Item D")をタップ
  3. 左端("Item A")が選択されてしまう

期待される動作 vs 実際の動作

期待される動作 実際の動作
右端をタップ "Item D"(index: 3)が選択される "Item A"(index: 0)が選択される

原因の推測

UIDesignRequiresCompatibilityYES の場合、iOS 26 の新しいデザインシステムとの互換性処理が行われる。この互換性処理において、動的に追加されたセグメントのヒットテスト領域が正しく計算されていない可能性があると推測している。

回避策

現時点で確認している回避策は以下の通りである。

回避策1: UIDesignRequiresCompatibility を NO にする

アプリの要件が許す場合、UIDesignRequiresCompatibilityNO に設定することで回避できる。

<key>UIDesignRequiresCompatibility</key>
<false/>

ただし、これにより iOS 26 の新しいデザインが適用されるため、UI全体に影響が出る可能性がある。前述した通り、移行計画上、このフラグをNOにするのはまだ先のため、我々はこの方法は採用できなかった。

回避策2: 静的なセグメントを使用する

Storyboard上でセグメントを静的に定義し、コードからの動的な変更を避けることで回避できる。ただし、動的にセグメントを変更する必要がある場合には使用できない。

試したが効果がなかった方法

layoutIfNeeded() を呼び出す

セグメント追加後に layoutIfNeeded() を呼び出すことで解決できるのではないかと考え、以下のコードを試したが、残念ながらこの方法では解決できなかった。

bottomSegmentedControl.setSegments(titles: ["Item A", "Item B", "Item C", "Item D"])
bottomSegmentedControl.layoutIfNeeded()

まとめ

iOS 26 / Xcode 26 環境で、UISegmentedControl のタップ位置がズレる不具合を確認した。

発生条件:

  • Xcode 26.x でビルド
  • UIDesignRequiresCompatibility = YES
  • Auto Layout で配置
  • セグメントを動的に設定

この不具合は Feedback Assistant で報告済みである。同様の問題に遭遇している開発者の参考になれば幸いだ。

この記事は iOS 26 / Xcode 26.2 時点の情報である。今後のアップデートで修正される可能性がある。

関連リンク

この記事をシェアする

FacebookHatena blogX

関連記事