↑クリックして拡大
↑クリックして拡大
↑クリックして拡大
↑クリックして拡大

頭痛が減ったので共有です!

rebuild.fmを応援しています!

HOME > willsetとdidsetでプロパティを監視

willsetとdidsetでプロパティを監視。意味あるのか???

クラスのプロパティにはWillsetとdidSetという監視用の関数があると聞いたのですが、用途は分かるにしても メリットとしてはどういうものなのかなと、getterやsetterと何が違うのか?うーん、と考えていました。調べていると海外のサイトでは同じように疑問にもつ質問があがっていました。 getとsetで同じことができるのでは?との私と同じスタンスです。解決されていましたので、順に説明していきます。

サンプル画像

参考:Swiftのプロパティ監視(willSet/didSet)の挙動について調べてみた
参考:Swift の変数やプロパティの値監視について
参考:swift willSet didSet and get set methods in a property
参考:What is the purpose of willSet and didSet in Swift?

調査してみた

以下のようなint型の変数があったとします、willsetとdidsetはgetterやsetterと同じことなのでは?との疑問です。


//didsetとwillsetを利用した場合
var HigeCnt_didsetAndwillset : Int = 0 {
    didSet {
        println (HigeCnt_didsetAndwillset)
    }
    willSet(newValue) {
    ..
    }
}
//従来のsetterとgetterを利用した場合
var HigeCnt_Normal: Int {
    get {
        return HigeCnt_Normal
    }
    set (newValue){
    }
}

上記は理解できます。

以下の方法ができるからwillsetとdidsetは違うんだ、らしいのですが、、、うーんいまいちわかっていません!


//http://stackoverflow.com/questions/24006234/what-is-the-purpose-of-willset-and-didset-in-swift
class Foo
{
    var propertyChangedListener : (Int, Int) -> Void = {
        println("The value of myProperty has changed from \($0) to \($1)")
    }

    var myProperty : Int = 0 {
        didSet { propertyChangedListener(oldValue, self.myProperty) }
    }
}

この上の処理がgetterとsetterにはできないようです。変数が変数を変更することかな?変更前データにアクセスすることでしょうか。

やってみた

上記に記載しましたが、oldValueにアクセスできること=自動で保存されていること、に旨味があるのかなと思いました。と思いましたが、 setterやgetterでもできますよね、うーん。ひとまず、上の変数から変数を呼び出す処理をgetterやsetterで書き換えられないものかやってみます。

一つわかったwillsetとdidsetのメリット


//willset と didset
class Foo
{
    var propertyChangedListener : (Int, Int) -> Void = {
        println("The value of myProperty has changed from \($0) to \($1)")
    }
    
    var myProperty : Int = 0 {
        didSet { propertyChangedListener(oldValue, self.myProperty) }
    }
}
//setterとgetter
class Foo2
{
    var propertyChangedListener : (Int, Int) -> Void = {
        println("The value of myProperty has changed from \($0) to \($1)")
    }
    
    var myProperty : Int {
        get {
            return self.myProperty
        }
        set (newValue){
            propertyChangedListener(self.myProperty, newValue);
        }
    }
}

この状態で以下を実行すると,,,,


    let foo:Foo = Foo();
    foo.myProperty = 1;
        
    let foo2:Foo2 = Foo2();
    foo2.myProperty = 2;//エラー

最初のwillsetとdidsetを利用する方法ならエラーが発生せず、0から1に変更されましたとログに表示。 foo2(getterとsetter)の場合は初期値がないのでエラー。setterやgetterを含める場合、初期値をセットすることはできない。init処理で セットしてあげないといけない。(参考URL:Set a default value for a property with defined getter and setter)

つまり、現状のすでに初期値もセットされているようなクラスに、この変数が変わった時に処理をいれたいな、、、、と思ったら、 現状のソースに影響させずにdidsetやwillsetを追加しやすい便利な関数なのかと腑に落ちました。他に利点があるのかもですが、ひとまずここまでにします。

まとめ

まとまらない状態で記事を書きすすめましたので支離滅裂してすいません、、、willsetとdidsetは私の考察では、 既存のクラスでなにかエラーが発生して、変数まわりが怪しいー>変数をwatchしてログ出力させたい時なんかに便利に利用できるのではと思いました。

↓こんな記事もありますよ!


2021-05-14 14:21:41

WatchOSのwatchconnectivityのFiletransferの落とし穴。と、避け方。

AppleWatch 実機だと成功するんだけど、シュミレーターだと失敗するという、、、 昔作成してた時は成功してたのになーと思って調べると、どうやら昔は成功してたみたい。watchOS6以降は...

2021-05-06 14:04:37

LINEのアニメーションスタンプ制作の落とし穴、、、失敗談

ゴールデンウィークにLINEスタンプを作成してみました。 作り切って申請も通したんですが、意図したアニメーションと違う、、、、 LINEクリエーターの画面だと、アニメーションのプレビュー...

2021-05-01 18:05:35

久しぶりのAdmobをobjective-cに実装。コンパイルエラーだらけ。バーミッション不具合でエミュレータにインスコできない。

忘れないようにメモ エミュレータにアプリをインストールする際にパーミッション系のエラーがでた時、また、iphone実機にインストールする際にも権限系のエラーが出る場合。 ターゲット→ex...
このエントリーをはてなブックマークに追加
右側のFacebookのLikeをクリック頂けると記事更新の際に通知されますので宜しければご利用下さい!