Swiftで遊ぼう! on Hatena

あしたさぬきblogでやってた初心者オヤジのiOSプログラミング奮闘記がHatenaに来ました

Swiftで遊ぼう! - 461- プロパティ・オブザーバー(Property Observers)

Beginning iPhone Development with Swift 3: Exploring the iOS SDK

Beginning iPhone Development with Swift 3: Exploring the iOS SDK

  • 作者: Molly K. Maskrey,Kim Topley,David Mark,Fredrik Olsson,JEFF LAMARCHE
  • 出版社/メーカー: Apress
  • 発売日: 2016/12/28
  • メディア: ペーパーバック
  • この商品を含むブログを見る

上記チュートリアル*1を再開しているのですが、Swift 3の文法の復習もします。

アクセス・コントロールの勉強をしているとプロパティ・オブザーバーの話が出ました。既に理解していたので、過去の記事で確認をしたところ、まともに説明しているページが無かったので、リファレンスとして使える説明をしてみます。

Swiftで遊ぼう! - 7 オブザーバー(Observers)? 夏だ! ビールサーバーがいい!:Life-LOG OtherSide

プロパティ・オブザーバーの勉強はかなり初期の頃にしていました。この頃は、どのような状況でこのプロパティを使うのか想像もできなかったので、なかなか理解できませんでした。1年勉強して存在理由が理解できるようになりました。しかし、えらく時間がかかってますね(^^;)

プロパティ(Properties)

Swiftで遊ぼう! - 166 - プロパティ(Properties):Life-LOG OtherSide

The Swift Programming Language (Swift 3): About Swiftを必ず確認する必要がありますが、プロパティに関する説明をまとめました。

1) Stored Properties(格納型プロパティ)

2) Computed Properties(計算型プロパティ)

  • set, get:セッターを省略すると、自動的に「newValue」が利用されます。
  • Read-Only Computed Properties

3) Property Observers

  • willSet, didSet:willSetは値を保持しないのでコンスタント値のパラメーターを()を使って与えないといけません。何も書かないと「newValue」に設定されます。 didSetも同様ですが、何も書かないと「oldValue」に設定されます。プロパティのイニシャライズ時に呼ばれませんが、プロパティに値が設定される度(同じ値だったとしても)に必ず呼ばれます。→ 下記に詳しい説明をします。

4) Type Properties

  • static var, class var

プロパティ・オブザーバー(Property Observers)

プロパティ・オブザーバーは、プロパティ値の変化を捉えて反応することができます。プロパティ・オブザーバーは、プロパティ値に値が設定される度に呼ばれます。これは同じ値が設定されても生じます。

どんなタイプでも格納型のプロパティににプロパティ・オブザーバーを設定することができますが、レイジー・格納型プロパティには設定できません。サブクラス内のオーバーライドした格納型、もしくは計算型プロパティにプロパティ・オブザーバーを設定することはできます。

オーバーライドしていない計算型プロパティの場合、計算型プロパティの「setter」で直接値の変化に反応することができるのでプロパティ・オブザーバーを加える必要はありません。

下記のどちらか、もしくはどちらも呼ぶことができます。

  1. willSet:値が設定される直前に呼ばれます。
  2. didSet:新しい値が設定された直後に呼ばれます。

willSetオブザーバーを設定する場合、定数パラメーターとして新しいプロパティが渡されます。自分で名前を付けることもできますが、パラメーター値を加えなければ「newValue」になります。
同様にdidSetオブザーバーを設定する場合も新しいパラメーター値が渡されますが、名前をつけなければ「oldValue」になります。

教科書の例文を少しだけ拡張して説明します。

class StepCounter {
    var totalSteps: Int = 0
    var addSteps: Int = 0 {
        willSet(newFoward) {
            totalSteps += newFoward
            print("当に今\(newFoward)歩がtotalStepsに追加されます。")
        }
        didSet {
            if addSteps > oldValue {
                print("\(addSteps - oldValue)歩前回より多いです。")
            } else {
                print("今回は前より歩数が少ないです。")
            }
            print("totalStepsは今\(totalSteps)歩になって今ます。")
        }
    }
}

このクラスから次のインスタンスを生成する。

var someSteps = StepCounter()
someSteps.addSteps = 200
someSteps.addSteps = 300
someSteps.addSteps = 100

するとコンソールに以下の表示が出ます。

当に今200歩がtotalStepsに追加されます。
200歩前回より多いです。
totalStepsは今200歩になっています。
当に今300歩がtotalStepsに追加されます。
100歩前回より多いです。
totalStepsは今500歩になっています。
当に今100歩がtotalStepsに追加されます。
今回は前より歩数が少ないです。
totalStepsは今600歩になっています。

まああまり説明は要りませんね。

今日はここまで。