「 プロパティの値の変化を監視したい… 」
「 値の変化を検知したタイミングで処理を実行したい… 」
SwiftUIの「onChange」は、プロパティの状態変化を監視する機能を持ちます。onChangeに状態を監視したいプロパティを設定しておくことで、プロパティの値の変更を検知して自動的に処理を呼び出すことができます。
本記事では、onChangeの機能解説と具体的な活用例について触れていきます!
[ 本記事はこんな人におすすめ ]
・SwiftUIでアプリ開発をしている
・onChangeの機能について知りたい
・onChangeの具体的な使い方を知りたい
環境・バージョン
> Swift 5.7.2
> Xcode 14.2
> macOS 13.0 Ventura
onChangeは監視したいプロパティが宣言されているView内の任意の場所に設定することができます。
引数「of:」に監視したいプロパティを設定します。
トレイリングクロージャ内に書かれている引数「newValue」には、監視プロパティの更新後の値が格納されており、クロージャの中でのみ使用できます。
また、この引数名は任意で設定が可能です。
例えば以下のコードでは、状態変数「inputText」を監視対象とすることで、TextFieldの文字入力によるプロパティの更新を検知して処理を実行しています。
struct BasicOnChangeView: View {
@State private var inputText = ""
var body: some View {
TextField("文字を入力", text: $inputText)
.onChange(of: inputText) { newValue in
print("プロパティの更新を検知: \(newValue)")
}
} // body
} // View
使用ケースによっては、「プロパティの更新前と更新後、両方の値を使いたい」という場合があります。
以下のように記述することで、更新前のプロパティ値を一緒に取得できます。更新前の値の引数名には、監視プロパティ自身の名前を記述します。
.onChange(of: inputText) { [inputText] newValue in
print("更新前の値: \(inputText)")
print("更新後の値: \(newValue)")
}
更新前の値にも任意の引数名を設定したい場合は、変数に代入する形で書くことができます。
例えば以下のコードでは更新前を「before」更新後を「after」と命名しています。
.onChange(of: inputText) { [before = inputText] after in
print("更新前の値: \(before)")
print("更新後の値: \(after)")
}
onChangeは複数のプロパティを監視対象とすることができます。引数「of:」に配列でプロパティを渡します。
この場合、監視対象のうちどれかの値が更新された時点で処理が実行されます。また、返ってくるnewValueの値も配列であることに注意してください。
struct MultipleOnChangeView: View {
@State private var inputText1: String = ""
@State private var inputText2: String = ""
var body: some View {
VStack {
TextField("一つ目のテキスト入力", text: $inputText1)
TextField("二つ目のテキスト入力", text: $inputText2)
}
.textFieldStyle(.roundedBorder)
.padding()
// 複数の値を監視対象に設定
.onChange(of: [inputText1, inputText2]) { newValue in
print(newValue)
}
} // body
} // View
onChangeに設定した処理は、監視対象としているプロパティの値に何らかの変化があったときのみ実行されます。
以下の例ではBoolプロパティに値を代入するボタンを二つ並べて、同じ値が代入されたときのonChangeの振る舞いを検証しています。
複数回同じボタンを押していますが、プロパティの値が(true -> false)または(false -> true)に変化する時のみ、onChangeの処理が発火していることがわかりますね。
Bool型以外の値(String, Int…)でも、onChangeは同様の動作をします。
渡されたプロパティを常に監視する振る舞いは、プロパティの状態による動的な制御が必要なときに活用できます。
例えば以下のコードでは、「テキスト入力の文字数が0(isEmpty)の時はボタンのアクションを自動で無効化する」という動作を実装しています。
ボタンアクションの有効無効を管理できる「disabled」モディファイアにBool型プロパティを渡しておいて、onChange内の条件文でBool値を動的に切り替えます。
struct DisableButtonOnChangeView: View {
@State private var inputText: String = ""
// 「disabled」モディファイアに渡すBool値
@State private var isDisable: Bool = true
var body: some View {
VStack {
TextField("文字を入力", text: $inputText)
.textFieldStyle(.roundedBorder)
.padding()
Button("完了") {
// 何らかの処理...
}
.buttonStyle(.borderedProminent)
.disabled(isDisable) // ⬅︎ trueで無効化
}
.onChange(of: inputText) { newValue in
if newValue.isEmpty {
isDisable = true
} else {
isDisable = false
}
}
} // body
} // View
ボックス内の文字数をonChangeが監視して、文字が入力されるとボタンが有効になり、文字数が0の時はボタンが無効化されていることがわかります。
また、onChangeによって更新されるプロパティの状態に合わせてViewの表示を切り替えるのも有効な方法です。
以下のコードでは、条件が当てはまったときに表示されるメッセージ文を追加しています。
VStack {
// 条件で表示管理されるメッセージ
if isDisable && inputText.isEmpty {
Text("文字を入力してください")
.foregroundColor(.red)
}
TextField("文字を入力", text: $inputText)
.textFieldStyle(.roundedBorder)
.padding()
Button("完了") {
// 何らかの処理...
}
.buttonStyle(.borderedProminent)
.disabled(isDisable) // ⬅︎ trueで無効化
}
Bool値の状態更新と合わせて、メッセージも表示されていますね。
このようにonChangeによるプロパティ更新との紐付けによって、様々な実装が可能です。
以上、SwiftUIの機能「onChange」についてでした!
要点をおさらいしておきましょう。
・プロパティの変更や更新を監視する
・「更新前」「更新後」両方の値を取得できる
・複数の値を監視対象に設定できる
・プロパティの値に変化があった時のみ、処理が実行される
onChangeを活用することで、プロパティの状態変化と紐づけられた様々なView表現や処理を実現することができます。SwiftUIでのアプリ開発において必須と言える機能なので、ぜひマスターしましょう👍
onChangeと親和性のある機能として、Viewが画面に表示されるタイミングを検知して処理を実行する「onAppear」があります。組み合わせることで実装の幅はさらに広がるでしょう。
【SwiftUI】onAppearの使い方と活用方法を徹底解説!
\ SHARE /
アプリ開発が学べる勉強会を開催中!
CodeCandyではアプリ開発を学ぶための勉強会を定期開催しています。
学習する習慣を身につけたい、他の参加者と作業したい、アプリ開発の基本をマスターしたい、という方のために無料で学べる勉強会です。
グループにメンバー登録して頂くと、イベント開催時にメールで通知されます。
徹底した基礎学習からマスターするiPhoneアプリ開発集中オンライン講座開講!
本書「iPhoneアプリ開発集中講座」を執筆している現役エンジニア講師陣が直接に指導!
基礎、課題実習で実践力を鍛えて、オリジナルアプリ公開までチャレンジ!
充実した転職支援もあるので、エンジニアへ転職したい人にもおすすめです!
まずは、現役エンジニアに相談できる無料相談をご利用ください。
2022年2月よりSwift学習を始め、4月からiOSアプリ開発オンラインスクール「CodeCandy」にてアプリ開発を学ぶ。 2023年10月に個人開発アプリ「unico」をリリース。現在はアプリの機能アップデートをしながら、スクール運営の技術ブログの執筆や、出版書籍の入稿チェック・デバッグにも携わる。