Swift転職なら=>【LevTech】
↑クリックして拡大
↑クリックして拡大
↑クリックして拡大
↑クリックして拡大

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

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してログ出力させたい時なんかに便利に利用できるのではと思いました。

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

関数引数の参照渡し Inout

Swiftで参照だけを渡す(呼び出し元の変数の値を変更する)にはどうしたらよいのかな〜と調査していると、関数引数に参照渡しする方法でindexinoutという言葉があることを知りました。紹介いたします

Rebuildfm(Poadcast)の技術話+オタ話が超絶に面白い、、、、、

去年の暮れ頃から聞いているPodcastを紹介します。IT企業の友人から「RebuldFM」が面白いよ〜と、私が Swiftサラリーマンを始めたことでSwiftの話をしてたら「知ってる知ってる」との話になって、どこで聞いたの? 「Rebuldfm」ってPodcastがあるんだよ、と。

UITabBarItem

タブバーを利用した時にアイコンがデフォルトのものだけでは物足りなかったのでフリー素材でよさそうなサイトがあったので共有です。 500個も魅力的でオーソドックスで使いやすいアイコン盛りたくさん。
このエントリーをはてなブックマークに追加
右側のFacebookのLikeをクリック頂けると記事更新の際に通知されますので宜しければご利用下さい!