[Swift] Swiftでのインスタンス変数を監視する方法

Swift

Swiftでclassやstructを宣言してメンバー変数を定義したときに、その値が変更されたときに何か処理したいことあります。その方法を説明します。
デバッグの時にも便利です。

環境&対象

内容を見直して、以下の環境で動作確認を行ないました。

  • macOS Monterery beta 5
  • Xcode 13 beta5
  • iOS 15 beta

プロパティ監視

Swift 言語そのものが、プロパティ変更を監視するための仕組みを提供しています。

Swiftが用意している仕組み
willSet
変更前に、ブロックを実行することができます
didSet
変更後に、ブロックを実行することができます

SwiftUIであれば、@State等の仕組みで、定義された変数の変更からビュー再構築ができますので、これらが使われるのは、変数の変更に合わせて特定の処理を行わせたい場合です。




willSet/didSet の使い方

以下は、alarmOnという変数が変更されると、updateAlarmTimerという関数が呼ばれます。

didSet example code

var alarmOn:Bool = false {
    didSet(newValue) {
        updateAlarmTimer()
    }
}

引数に、新しい値(newValue)が渡されるので、必要であれば参照できます。

@Stateとの組み合わせは、別の方法が必要

SwiftUIの仕組みを使いたいのであれば、@State を使うことが多くなりますが、その時には、didSet は期待通りに動きません。

以下のように、onChange を使用して、変更を監視する必要があります。

/
//  ContentView.swift
//
//  Created by : Tomoaki Yagishita on 2021/09/09
//  © 2021  SmallDeskSoftware
//

import SwiftUI

struct ContentView: View {
    // (1)
    @State private var text:String = "Hello, world!"
    var body: some View {
        VStack {
            TextField("input", text: $text)
                .textFieldStyle(.roundedBorder)
                .padding()
            Text("Input value: \(text)")
                .padding()
        }
        // (2)
        .onChange(of: text) { newValue in
            print("Text is changed to \(newValue)")
        }
        .padding()
    }
}
コード解説
  1. @State を使って定義した変数
  2. (1) で定義した変数の変更を監視
Update at 2021.Sep.9
正しくない説明でしたので、修正しました。
@State に対しての didSet は、期待通りの動作をしません。

まとめ:Swiftでのインスタンス変数を監視する方法

Swiftでのインスタンス変数を監視する方法
  • 通常の変数であれば、 willSet/didSet で変更を検知できる
  • @State については、onChange を使用して監視する必要がある

説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です