簡體   English   中英

當我設置該屬性的屬性時,為什么在屬性上調用'didset'?

[英]Why is 'didset' called on a property when I set the property of that property?

在此代碼中,當文本更改時,將調用titleEditingChanged (如預期的那樣)。 但是當它執行該行時

investment?.title = sender.text!

它稱Investmentdidset{} 為什么?

class InvestmentCell: UITableViewCell {

    var investment: Investment? {
        didSet {
            // setup UI elements from class properties
            textField.text = investment?.title
            valueField.text = investment?.value?.description
        }
    }

    @IBAction func titleEditingChanged(sender: UITextField) {
        investment?.title = sender.text!
    }

    @IBOutlet weak var textField: UITextField!
    @IBOutlet weak var valueField: UITextField!
}

當設置類型實例的底層屬性時,也會調用值類型 (例如結構)的屬性觀察者; 只是因為實例本身值已更新 同樣不適用於參考類型 ; 只要引用本身沒有變異,就不會調用屬性觀察者(即,引用本身可以被認為是引用類型的值)。

語言指南 - 屬性 -我們讀到的屬性觀察者

財產觀察員觀察並回應財產價值的變化 每次設置屬性值時都會調用屬性觀察者,即使新值與屬性的當前值相同


要驗證上述內容,請考慮以下示例:

/* reference type */
class InvestmentC {
    var title: String = "Foo"
}

/* value type */
struct InvestmentS {
    var title: String = "bar"
}

class InvestmentContainer {
    var investmentC : InvestmentC {
        didSet {
            print("did set a property of 'InvestmentC' instance (ref. type)")
        }
    }

    var investmentS : InvestmentS {
        didSet {
            print("did set a property of 'InvestmentS' instance (val. type)")
        }
    }

    init() {
        investmentC = InvestmentC()
        investmentS = InvestmentS()
    }
}

/* Example: property observer called only when setting a property
            of the value type instance 'investmentC'              */
let foo = InvestmentContainer()
foo.investmentC.title = "foobar" // prints: nothing
foo.investmentS.title = "foobar" // prints: "did set a property of 'InvestmentS' instance (val. type)"

因此,我們可以推斷出您的自定義類型Investment是一種值類型(結構),並且即使您只設置/更新此基礎屬性,也將調用此類型實例investmentdidSet屬性觀察者(在您的UITableViewCell子類中) investment 如果您想避免這種情況, didSet Investment更改為引用類型(類),在這種情況下,只有在設置/更新investment實例本身時才會更改didSet屬性觀察者。

這是因為Investment可能是一個結構,而不是一個類。 在Swift中,結構是值類型,而不是類的引用類型。 因此,結構不是“可變的”。

這意味着每當您更改struct屬性時,都會分配一個新的struct對象來替換當前的對象,當前的對象數據將被復制到新的對象數據,但更改的屬性將包含新的值集。

請記住,每當使用let命令初始化struct對象時,編譯器都不允許您更改struct屬性(使用類可以執行此操作)。

這就解釋了為什么每次更改struct屬性時都會調用觀察者。 一旦分配了新的struct對象來替換當前的對象,它現在將被存儲在另一個內存塊中,因此它的值將被更改並且將調用didSet觀察者。

PS:如果將Investment定義為類而不是結構,則不會發生這種情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM