以前は lazy var
に didSet
を設定することはできませんでしたが、Swift 5.7 よりもっと前のタイミングでそれができるようになっています。
class Object {
lazy var test: Int = 0 {
didSet {
print("TEST")
}
}
}
そうなると didSet
が呼び出されるタイミングが気になってくるところですけれど、これについてはシンプルで、lazy var
の宣言時に指定した初期値が必要になったタイミングだけを初期化フェーズとして捉える様子です。didSet
は初期化フェイズでは実行されず、代入フェーズになってから呼び出されることになります。
lazy var
では、代入前に参照するかどうかで、宣言時に指定した初期値で初期化されるか違ってきますけれど、初期値を使っているかに関わらず、代入時には既に初期化が終わっているものとして代入フェーズで値の割り当てが行われ、それにより didSet
が実行される様子です。このとき、未参照な状態であれば、初期値が使われることがないのは didSet
を伴わない lazy var
と同様です。
// ここの初期値が採用される時に限り、初期化フェーズとして扱われる様子
lazy var test: Int = 0
// 宣言時の初期値が使われたかに関わらず、代入フェーズとして扱われる様子
test = 1
ここで気になるのは「それでは didSet
内で oldValue
を参照したらどうなるか」というところですけれど、この場合はつまり最初の代入時に初期値が必要になるため、この時点で自身が参照されたものとして、この時は宣言時に指定した初期値が生成されて oldValue
として参照できるようになります。
lazy var test: Int = 0 {
didSet {
// 参照前に代入したとしても didSet が実行され、
// その中で oldValue を参照したとき、宣言時の初期値が oldValue に割り当てられる
print("TEST", oldValue)
}
}