📚

[SwiftUI] iOS17対応版!`onChange(of:perform:)`の非推奨と新しい使い方まとめ

に公開

SwiftUIのアップデートで注目すべきポイントのひとつ、
onChange(of:perform:)がiOS17から非推奨(deprecated)になりました。

これにより、今までの書き方が整理され、
よりシンプルで直感的なAPIへと進化しています。

https://developer.apple.com/documentation/swiftui/view/onchange(of:initial:_:)


新しいonChangeの使い方

クロージャの形式は「0個」か「2個」

新しいonChangeでは、クロージャの引数が「なし」または「2つ」に統一されました。

1. 引数なしの場合

変化前後の値を使わない場合は、次のように記述します。

.onChange(of: value) {
    // 変化があったら実行
}

2. 引数2つ(oldValue, newValue)の場合

変化前と変化後の両方の値を使いたい場合はこちら。

.onChange(of: value) { oldValue, newValue in
    // oldValue と newValue を使って処理
}

状態の移り変わりをより繊細に追跡できるので、
データ比較や特殊な条件分岐に便利です。


initialオプションとは?

新たに、initial: trueオプションが追加されました。
これを指定すると、ビューの初回表示時にもクロージャが実行されます。

.onChange(of: value, initial: true) {
    // 初回表示時も実行される
}

initial: trueを使うときの注意点

初回実行時は oldValuenewValue が同じ値になるため、
差分検出ロジックには一工夫が必要です。
(差がない場合でもクロージャは呼び出されます)

https://developer.apple.com/documentation/swiftui/view/onchange(of:initial:_:)


コード比較:変更前と変更後

変更前:

.onChange(of: selectedIcon) { newValue in
    if newValue == "Default" {
        changeAppIcon(to: nil)
    } else {
        changeAppIcon(to: newValue)
    }
}

変更後:

.onChange(of: selectedIcon) {
    if selectedIcon == "Default" {
        changeAppIcon(to: nil)
    } else {
        changeAppIcon(to: selectedIcon)
    }
}

コードがよりスッキリし、読みやすさも向上します。


oldValuenewValueを活用しよう

iOS17以降、onChangeのクロージャでoldValuenewValueの両方が取れるようになり、
状態の変化をより細かくハンドリングできるようになりました。

例えば、アプリのライフサイクル管理ではこう使えます。

.onChange(of: scenePhase) { oldValue, newValue in
    if oldValue == .active && newValue == .inactive {
        // アクティブから非アクティブへの遷移を検知
    }
}

これにより、以前のように手動で状態を保存・比較する手間が減り、
コードの保守性も向上します。

https://developer.apple.com/documentation/swiftui/view/onchange(of:initial:_:)


まとめ:SwiftUIをもっと快適に

今回の変更は「クロージャの書き方が変わった」くらいの感覚でOKです。

既存コードもそのまま動く場合が多く、
移行はそこまで大がかりにはなりません。

とはいえ、新しい書き方に慣れておくことで、
これからのSwiftUI開発がさらに快適になること間違いなし。

ぜひこの機会に、新しいonChangeスタイルをマスターしておきましょう!

Discussion