【Swift/SwiftUI】プロパティオブザーバwillSetとdidSetの使い方

本記事では、構造体などのプロパティを更新する際に使用できるプロパティオブザーバの基本的な使い方について解説していきます。

プロパティオブザーバとは

構造体などのプロパティに対して値を代入するなどによって、変数の値が変化するときに処理を実行することができる仕組みです。

プロパティの更新される前に実行される「wilSet」とプロパティの更新後に実行される「didSet」の2種類のプロパティオブザーバが存在します。

プロパティオブザーバの使用により、アプリケーション内で値変更前後のログを記録したり、プロパティの古い値を保存しておくなどの動きも簡単に実装することができます。

プロパティオブザーバの実装

それぞれのプロパティオブザーバを実装しつつ、それぞれのタイミングと用途について解説していきます。

プロパティの値代入直前の処理

willSetを使用してプロパティに値が代入される直前に処理を行うためには、
以下のように「変数宣言{ willSet{ 処理 } }」という形式で記述します。

struct NumList {
    var oldNums : [Int] = []
    var countNum: Int = 0 {
        willSet {
            print(" \(countNum) から \(newValue) に値が変更される")
            oldNums.append(countNum)
        }
    }
}

var count = NumList()
count.countNum = 1
print(count.oldNums)

//実行結果
0 から 1 に値が変更される
[0]

上記の例では、構造体の中にoldNumsという空の配列とcountNumという初期値が0でwillSetを持つ変数を用意しています。willSetの中では代入される値と代入前の値を出力し、oldNumsに元々の値を保存しています。

実際に構造体をインスタンス化して、countNumに値を代入してみると代入の直前にwillSetの処理が実行されることが確認できます。willSet内ではnewValueという変数名でこれからcountNumに代入される値を取得して利用することができます。

また、countNumを代入したoldNumsの出力結果が[0]となっていることから、値の代入前に処理が実行されていることが確認できます。

プロパティの値代入直後の処理

didSetを使用してプロパティに値が代入された直後に処理を行うためには、
以下のように「変数宣言{ didSet{ 処理 } }」という形式で記述します。

struct NumList {
    var oldNums : [Int] = []
    var countNum: Int = 0 {
        didSet {
            oldNums.append(oldValue)
            print(" \(oldValue) から \(countNum) に値が変更された")
        }
    }
}

var count = NumList()
count.countNum = 1
print(count.oldNums)

//実行結果
0 から 1 に値が変更された
[0]

上記の例では、構造体の中にoldNumsという空の配列とcountNumという初期値が0でdidSetを持つ変数を用意しています。didSetの中では代入された値と代入前の値を出力し、oldNumsに元々の値を保存しています。

実際に構造体をインスタンス化して、countNumに値を代入してみると代入の直後にdidSetの処理が実行されることが確認できます。didSet内ではoldValueという変数名でcountNumに代入される前の値を取得して利用することができます。

また、oldValueを代入したoldNumsの出力結果が[0]となっていることから、値の代入後に処理が実行されていることが確認できます。

最後に

本記事では、willSetとdidSetを使用してプロパティへの値の代入前後で処理を実行したり、値を保持しておく方法について解説してきました。

他にも構造体の定義と利用方法や関数の宣言と使用方法などについても解説する記事を書いていますのでぜひそちらもご確認ください。