Sponsor Link
環境&対象
- macOS14.2 Beta 3
- Xcode 15.1 beta 3
- iOS 17.2
- Swift 5.9
onChange
onChange は、Value 型変数の更新に伴って、何らかの動作を行いたいときに使うことのできる View Modifier です。
2023.Nov 時点では、以下の 2種類用意されています。
・変更されたときに実行する動作を指定する ViewModifier
・変更された時の変更前後の値を参照しながら、動作を指定できる ViewModifier
onChange は、Equatable の性質を利用して 変更されたかどうかの判定を行います。
つまり、監視対象の変数は、Equatable に準拠していないといけません。
値なし
(シンプルな方の) onChange の signature は、以下の通りです。
public func onChange(of value: V, initial: Bool = false, _ action: @escaping () -> Void) -> some View where V : Equatable
value として指定した変数が変更されたときに、action として指定された closure が実行されます。
使用例
以下は使用例です。
ボタンが押下され、変数の値が+1されたときに、print 文が実行されます。
//
// ContentView.swift
//
// Created by : Tomoaki Yagishita on 2023/11/23
// © 2023 SmallDeskSoftware
//
import SwiftUI
struct ContentView: View {
@State private var count = 0
var body: some View {
VStack {
Text("Count: \(count)")
Button(action: {
count += 1
}, label: { Text("+1") })
}
.onChange(of: count) {
print("count is changed !")
}
.padding()
}
}
#Preview {
ContentView()
}
Button を押下すると、コンソールに “count is changed !” と表示されます。
これは、count が変更されると onChange が呼び出されるためです。
値付き
変数を監視しているときに、変更された事実だけではなく 変更された値(と 以前の値)がほしいケースがあります。
そのように、変更前後の値を closure に渡してくれる onChange も用意されています。
signature は以下のようになっています。
public func onChange(of value: V, initial: Bool = false, _ action: @escaping (_ oldValue: V, _ newValue: V) -> Void) -> some View where V : Equatable
この onChange を使用すると、以下のように 変更前後の値を使用した処理を実行させることが可能です。
//
// ContentView.swift
//
// Created by : Tomoaki Yagishita on 2023/11/23
// © 2023 SmallDeskSoftware
//
import SwiftUI
struct ContentView: View {
@State private var count = 0
var body: some View {
VStack {
Text("Count: \(count)")
Button(action: {
count += 1
}, label: { Text("+1") })
}
.onChange(of: count) { (oldValue, newValue) in
print("count is changed ! \(oldValue) -> \(newValue)")
}
.padding()
}
}
#Preview {
ContentView()
}
上記の例では、oldValue, newValue として 変更前後の値を参照しています。
onChange の initial 引数
onChange の 2 つの signature をよく見ると、initial という引数があります。
この initial という引数を使用すると、View が表示されるタイミングで onChange を実行させることができます。いわゆる onAppear 相当の処理になります。
なお、変更前後の値が渡される onChange には、変更前 と 変更後の値として同じ値が渡されてきます。
試した範囲では onAppear と onChange(initial: true) の呼び出し順序は、記述の順序になっていましたが、ドキュメントには特に記載はありません。
onChange (iOS16/macOS13以前)
onChange という ViewModifier は、iOS17/macOS14 以前にも存在していましたが、すこし signature が異なりました。
public func onChange(of value: V, perform action: @escaping (_ newValue: V) -> Void) -> some View where V : Equatable
上記のように、新規の値のみが 渡されてきていました。
この onChange でも Swift の機能である キャプチャ を使用することで 変更前の値を参照することはできました。
[Swift][SwiftUI] willSet/didSet/onChange の使い方
まとめ
onChange は、iOS17/macOS14 で signature が更新されて 2種類の onChange になった。
- 変数の値情報なしに、closure を実行する onChange
- 変更前後の値情報を与えられる closure を実行する onChange
- initial を指定することで、onAppear 時に実行させることも可能になった
- MainThread で実行されることがあるため、時間のかかる処理を書かない方が良いのは同じ
説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。
SwiftUI おすすめ本
SwiftUI を理解するには、以下の本がおすすめです。
SwiftUI ViewMatery
SwiftUI で開発していくときに、ViewやLayoutのための適切なmodifierを探すのが大変です。
英語での説明になってしまいますが、以下の”SwiftUI Views Mastery Bundle”という本がビジュアル的に確認して探せるので、便利です。
英語ではありますが、1ページに コードと画面が並んでいるので、非常にわかりやすいです。
View に適用できる modifier もわかりやすく説明されているので、ビューの理解だけではなく、どのような装飾ができるかも簡単にわかります。
超便利です
販売元のページは、こちらです。
SwiftUI 徹底入門
# SwiftUI は、毎年大きく改善されていますので、少し古くなってしまいましたが、いまでも 定番本です。
Swift学習におすすめの本
詳解Swift
Swift の学習には、詳解 Swift という書籍が、おすすめです。
著者は、Swift の初期から書籍を出していますし、Swift の前に主力言語だった Objective-C という言語についても同様の書籍を出しています。
最新版を購入するのがおすすめです。
現時点では、上記の Swift 5 に対応した第5版が最新版です。
Sponsor Link