値の変更を検知するonChangeモディファイアの使い方を解説します。
環境
この記事の情報は次のバージョンで動作確認しています。
【Xcode】12.5RC
【Swift】5.4
【iOS】14.5
【macOS】Big Sur バージョン 11.5.2
【Swift】5.4
【iOS】14.5
【macOS】Big Sur バージョン 11.5.2
基本的な使い方
1 2 3 |
.onChange(of: 値, perform: クロージャー) |
【引数】
of
監視対象の値。この値が変更されると、performで指定されたクロージャーが実行されます。
perform
監視対象の値が変更された時に実行するクロージャー。
クロージャーはメインスレッドで実行されるので、長時間実行されるタスクは、バックグラウンドのキューに送る必要があります。
クロージャーでは引数として監視対象の変更後の値を受け取ります。
onChangeモディファイアを記述する場所は、値のスコープ範囲内であればどこでも良いです。
使用例
TextFieldにバインドされた値が変更される度にonChangeが呼ばれます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
struct ContentView: View { @State private var inputValue = "" var body: some View { Form { TextField("文字列を入力してください", text: $inputValue) } .onChange(of: inputValue) { newValue in print("newValue = [\(newValue)]") } } } |
変更前の値を受け取る
クロージャーを次のように記述すると、変更前の値が受け取れます。
1 2 3 4 5 |
.onChange(of: 値) { [変更前プロパティ名] 変更後プロパティ名 in // 処理 } |
注意点として、変更後プロパティ名は任意に指定できますが、変更前プロパティはスコープ内の実プロパティ名でなければいけません。
使用例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
struct ContentView: View { @State private var inputValue = "" var body: some View { Form { TextField("文字列を入力してください", text: $inputValue) } .onChange(of: inputValue) { [inputValue] newValue in print("oldValue = [\(inputValue)], newValue = [\(newValue)]") } } } |
onChangeを複数記述したらどうなるのか?
監視対象が同一のonChangeを複数記述した場合、どちらも実行されるようです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
struct ContentView: View { @State private var inputValue = "" var body: some View { Form { TextField("文字列を入力してください", text: $inputValue) .onChange(of: inputValue) {newValue in print("②newValue = [\(newValue)]") } } .onChange(of: inputValue) {newValue in print("①newValue = [\(newValue)]") } } } |
クロージャー内で再度値を変更したらどうなるのか?
onChange()のクロージャー内で、監視対象のプロパティを変更した場合、2回までは繰り返し実行されますが、以降はエラーメッセージが出て実行されません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
struct ContentView: View { @State private var inputValue = "" var body: some View { Form { TextField("文字列を入力してください", text: $inputValue) } .onChange(of: inputValue) {newValue in print("newValue = [\(newValue)]") inputValue += "+" } } } |
あわせて読みたい記事
(アーカイブ)【SwiftUI】TextFieldの使い方
(2020/09/26 更新) 本記事で使用しているTextFieldの使い方はiOS14以前の仕様を元に解説しています。 最新の情報はこちらの記事を御覧ください。 テキスト入力に使うTextField()の使い方を解説します。