willSet和didSet

屬性觀察 (Property Observers) 是 Swift 中一個很特殊的特性溃论,利用屬性觀察我們可以在當(dāng)前類型內(nèi)監(jiān)視對于屬性的設(shè)定年扩,并作出一些響應(yīng)饭于。Swift 中為我們提供了兩個屬性觀察的方法澜汤,它們分別是 willSet 和 didSet。

使用這兩個方法十分簡單唇辨,我們只要在屬性聲明的時候添加相應(yīng)的代碼塊鸯绿,就可以對將要設(shè)定的值和已經(jīng)設(shè)置的值進行監(jiān)聽了:

class MyClass {
    var date: NSDate {
        willSet {
            let d = date
            print("即將將日期從 \(d) 設(shè)定至 \(newValue)")
        }
        
        didSet {
            print("已經(jīng)將日期從 \(oldValue) 設(shè)定至 \(date)")
        }
    }
    
    init() {
        date = NSDate()
    }
}
let foo = MyClass()
foo.date = foo.date.dateByAddingTimeInterval(10086)

// 輸出
// 即將將日期從 2014-08-23 12:47:36 +0000 設(shè)定至 2014-08-23 15:35:42 +0000
// 已經(jīng)將日期從 2014-08-23 12:47:36 +0000 設(shè)定至 2014-08-23 15:35:42 +0000

在 willSet 和 didSet 中我們分別可以使用 newValue 和 oldValue 來獲取將要設(shè)定的和已經(jīng)設(shè)定的值拇厢。屬性觀察的一個重要用處是作為設(shè)置值的驗證满粗,比如上面的例子中我們不希望 date 超過當(dāng)前時間的一年以上的話辈末,我們可以將 didSet 修改一下:

class MyClass {
    let oneYearInSecond: TimeInterval = 365 * 24 * 60 * 60
    var date: NSDate {
        
        //...
        
        didSet {
            if (date.timeIntervalSinceNow > oneYearInSecond) {
                print("設(shè)定的時間太晚了!")
                date = NSDate().addingTimeInterval(oneYearInSecond)
            }
            print("已經(jīng)將日期從 \(oldValue) 設(shè)定至 \(date)")
        }
    }
    
    //...
}

更改一下調(diào)用映皆,我們就能看到效果:

// 365 * 24 * 60 * 60 = 31_536_000
foo.date = foo.date.dateByAddingTimeInterval(100_000_000)

// 輸出
// 即將將日期從 2014-08-23 13:24:14 +0000 設(shè)定至 2017-10-23 23:10:54 +0000
// 設(shè)定的時間太晚了挤聘!
// 已經(jīng)將日期從 2014-08-23 13:24:14 +0000 設(shè)定至 2015-08-23 13:24:14 +0000

初始化方法對屬性的設(shè)定,以及在 willSet 和 didSet 中對屬性的再次設(shè)定都不會再次觸發(fā)屬性觀察的調(diào)用劫扒,一般來說這會是你所需要的行為檬洞,可以放心使用能夠。

我們知道沟饥,在 Swift 中所聲明的屬性包括存儲屬性和計算屬性兩種。其中存儲屬性將會在內(nèi)存中實際分配地址對屬性進行存儲,而計算屬性則不包括背后的存儲贤旷,只是提供 set 和 get 兩種方法广料。在同一個類型中,屬性觀察和計算屬性是不能同時共存的幼驶。也就是說艾杏,想在一個屬性定義中同時出現(xiàn) set 和 willSet 或 didSet 是一件辦不到的事情。計算屬性中我們可以通過改寫 set 中的內(nèi)容來達到和 willSet 及 didSet 同樣的屬性觀察的目的盅藻。如果我們無法改動這個類购桑,又想要通過屬性觀察做一些事情的話,可能就需要子類化這個類氏淑,并且重寫它的屬性了勃蜘。重寫的屬性并不知道父類屬性的具體實現(xiàn)情況,而只從父類屬性中繼承名字和類型假残,因此在子類的重載屬性中我們是可以對父類的屬性任意地添加屬性觀察的缭贡,而不用在意父類中到底是存儲屬性還是計算屬性:

class A {
    var number :Int {
        get {
            print("get")
            return 1
        }
        
        set {print("set")}
    }
}

class B: A {
    override var number: Int {
        willSet {print("willSet")}
        didSet {print("didSet")}
    }
}

調(diào)用 number 的 set 方法可以看到工作的順序

let b = B()
b.number = 0

// 輸出
// get
// willSet
// set
// didSet

set 和對應(yīng)的屬性觀察的調(diào)用都在我們的預(yù)想之中。這里要注意的是 get 首先被調(diào)用了一次辉懒。這是因為我們實現(xiàn)了 didSet阳惹,didSet 中會用到 oldValue,而這個值需要在整個 set 動作之前進行獲取并存儲待用眶俩,否則將無法確保正確性莹汤。如果我們不實現(xiàn) didSet 的話,這次 get 操作也將不存在颠印。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末纲岭,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子嗽仪,更是在濱河造成了極大的恐慌荒勇,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件闻坚,死亡現(xiàn)場離奇詭異沽翔,居然都是意外死亡,警方通過查閱死者的電腦和手機窿凤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門仅偎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人雳殊,你說我怎么就攤上這事橘沥。” “怎么了夯秃?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵座咆,是天一觀的道長痢艺。 經(jīng)常有香客問我,道長介陶,這世上最難降的妖魔是什么堤舒? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮哺呜,結(jié)果婚禮上舌缤,老公的妹妹穿的比我還像新娘。我一直安慰自己某残,他們只是感情好国撵,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著玻墅,像睡著了一般介牙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上椭豫,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天耻瑟,我揣著相機與錄音,去河邊找鬼赏酥。 笑死喳整,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的裸扶。 我是一名探鬼主播框都,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼呵晨!你這毒婦竟也來了魏保?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤摸屠,失蹤者是張志新(化名)和其女友劉穎谓罗,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體季二,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡檩咱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了胯舷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片刻蚯。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖桑嘶,靈堂內(nèi)的尸體忽然破棺而出炊汹,到底是詐尸還是另有隱情,我是刑警寧澤逃顶,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布讨便,位于F島的核電站充甚,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏器钟。R本人自食惡果不足惜津坑,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一妙蔗、第九天 我趴在偏房一處隱蔽的房頂上張望傲霸。 院中可真熱鬧,春花似錦眉反、人聲如沸昙啄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽梳凛。三九已至,卻和暖如春梳杏,著一層夾襖步出監(jiān)牢的瞬間韧拒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工十性, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留叛溢,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓劲适,卻偏偏與公主長得像楷掉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子霞势,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容