[iOS] 「UISegmentedControlの生成処理」のiOS 14と13以前との間の差異について

本記事では、「UISegmentedControlの生成処理」のiOS 14と13以前との間の差異を紹介します。
2020.10.06

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんばんは。CX事業本部の平屋です。

本記事では、「UISegmentedControlの生成処理」のiOS 14と13以前との間の差異を紹介します。

検証環境

  • macOS Mojave 10.15.6
  • Xcode Version 12.0.1 (12A7300)

差異の発生条件

以下のようにUISegmentedControlのサブクラスでinit(frame:)init(items:)を実装し、init(items:)を使用してインスタンスを生成した場合に、iOS 14と13以前との間で差異が発生しました。

class CustomSegmentedControl: UISegmentedControl {
    required init?(coder: NSCoder) {
        // ...
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        
        // 初期化処理A
    }

    override init(items: [Any]?) {
        super.init(items: items)
        
        // 初期化処理B
    }
}

class ViewController: UIViewController {
    // ...

    func prepare() {
        // カスタムのSegmentedControlをコードで生成する
        let segmentedControl = CustomSegmentedControl(items: ["first", "second"])

        // ...
    }
}

iOS 13以前の場合の動作

init(items:)を使用してインスタンスを生成すると、以下の順番で処理が行われます。

  • init(items:)が呼ばれる
  • init(frame:)が呼ばれる
  • init(frame:)内の初期化処理Aが実行される
  • init(items:)内の初期化処理Bが実行される

初期化の過程でinit(frame:)も呼ばれます。

iOS 14以降の場合の動作

init(items:)を使用してインスタンスを生成すると、以下の順番で処理が行われます。

  • init(items:)が呼ばれる
  • init(items:)内の初期化処理Bが実行される

初期化の過程でinit(frame:)は呼ばれず、初期化処理Aも実行されません。

さいごに

本記事では、「UISegmentedControlの生成処理」のiOS 14と13以前との間の差異を紹介しました。Xcode 12対応を行っているアプリで、iOS 14の場合だけSegmentedControlの初期化処理が正常に行われず、原因を調査していくとこの差異を発見しました。

iOS 14で以下のメソッドの追加などが行われているので、その影響で内部の実装も変わったんでしょうか?

Xcode 12対応の作業をされている方の参考になれば幸いです。