# property observer (willSet/didSet)

[Swift](https://lochiwei.gitbook.io/ios/swift) ⟩ [type](https://lochiwei.gitbook.io/ios/swift/type) ⟩ [property](https://lochiwei.gitbook.io/ios/swift/type/prop) ⟩ [stored](https://lochiwei.gitbook.io/ios/swift/type/prop/stored-property) ⟩ property observer

{% hint style="success" %}
:scales: [willset-didset-vs.-get-set](https://lochiwei.gitbook.io/ios/swift/type/prop/willset-didset-vs.-get-set "mention")

* 只需<mark style="color:yellow;">監控屬性變化</mark>或<mark style="color:yellow;">執行副作用</mark>，用 <mark style="color:purple;">willSet</mark>/<mark style="color:purple;">didSet</mark> (*<mark style="color:purple;">property observer</mark>*)
* 需主動<mark style="color:yellow;">調整</mark>或<mark style="color:yellow;">限制屬性值</mark>時，用 [get/set](https://lochiwei.gitbook.io/ios/swift/type/prop/computed-properties)。
* <mark style="color:purple;">willSet</mark>：在<mark style="color:yellow;">變更</mark><mark style="color:red;">前</mark>的準備工作，如：檢查、備份舊值或發出警告。
* <mark style="color:purple;">didSet</mark>：監控<mark style="color:yellow;">變更</mark><mark style="color:red;">後</mark>的處理，如：限制範圍、觸發事件或更新 UI。
* <mark style="color:purple;">willSet</mark> <mark style="color:red;">無法阻止或改變</mark><mark style="color:yellow;">屬性值的設定</mark>，但 <mark style="color:purple;">didSet</mark> <mark style="color:green;">可進行修正</mark>。
  {% endhint %}

{% hint style="warning" %} <mark style="color:purple;">willSet</mark>/<mark style="color:purple;">didSet</mark> 是給 [stored property](https://lochiwei.gitbook.io/ios/swift/type/prop/stored-property) 用的，[computed property](https://lochiwei.gitbook.io/ios/swift/type/prop/computed-properties) 不能用:exclamation:

:scales: [stored-vs.-computed](https://lochiwei.gitbook.io/ios/swift/type/prop/stored-vs.-computed "mention")
{% endhint %}

* *<mark style="color:purple;">Property observers</mark>* are <mark style="color:yellow;">called every time</mark> a <mark style="color:yellow;">property’s value is</mark> <mark style="color:red;">set</mark>, <mark style="color:red;">even if</mark> the <mark style="color:yellow;">new value is the same</mark> as the property’s current value.
  * <mark style="color:blue;">`willSet`</mark> is called <mark style="color:yellow;">just before</mark> the value is stored.
  * <mark style="color:blue;">`didSet`</mark> is called <mark style="color:yellow;">immediately after</mark> the new value is stored.
* You can add *<mark style="color:purple;">property observers</mark>* in the following places:
  * <mark style="color:orange;">stored properties</mark> that you <mark style="color:yellow;">define</mark>╱[inherit](https://lochiwei.gitbook.io/ios/swift/type/inheritance).
  * [computed properties](https://lochiwei.gitbook.io/ios/swift/type/prop/computed-properties) that you [inherit](https://lochiwei.gitbook.io/ios/swift/type/inheritance).

{% tabs %}
{% tab title="💈範例" %}

```swift
struct Example {
    
    // ⭐️ stored property
    var value: Int = 0 {
    
        // ⭐️ property observer examples
        
        willSet {
            // ⭐️ willSet 隱含一個 newValue 變數，指即將要變更的新屬性值
            print("value 即將被設定為 \(newValue)")
        }
        
        // ---------------------------------------
        
        // 狀況一：只做紀錄，不做任何修改
        didSet {
            // ⭐️ didSet 隱含一個 oldValue 變數，用來存取舊的屬性值
            print("value 從 \(oldValue) 改為 \(value)")
        }
        
        // 狀況二：除了監控外，再做修改
        // (如果是這種情況，可考慮用 computed property (get/set))
        didSet {
            if value < 3 {
                print("value 小於 3，自動調整為 3")
                // ⭐️ didSet 內可重新設定屬性值，
                // ❗️ 但不會再觸發 didSet，以免無限循環。
                value = 3
            }
        }
        
    }// value
}
```

{% endtab %}

{% tab title="📘 手冊" %}

* Swift ⟩ [Properties](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/properties/) ⟩ [Property Observers](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/properties/#Property-Observers) &#x20;
  {% endtab %}

{% tab title="👥 相關" %}

* [computed-properties](https://lochiwei.gitbook.io/ios/swift/type/prop/computed-properties "mention")
  {% endtab %}
  {% endtabs %}
