为什么'确实'当我设置该属性的属性时调用属性?

时间:2016-03-08 15:23:23

标签: ios swift

在此代码中,当文本更改时,将调用titleEditingChanged(按预期方式)。但是当它执行行

investment?.title = sender.text!

它调用didset{}的{​​{1}}。 为什么呢?

Investment

2 个答案:

答案 0 :(得分:13)

当设置类型实例的基础属性时,也会调用值类型(例如结构)的属性观察者;只是因为实例本身的值已更新。同样的不适用于引用类型;只要引用本身没有变异,就不会调用属性观察者(即,引用本身可以被认为是引用类型的值)。

Language Guide - Properties - Property Observers我们读到:

  

财产观察员观察并回应房产中的变化   值。每次物业的价值都会调用物业观察员   设置,即使新值与属性的当前值

相同

要验证上述内容,请考虑以下示例:

/* 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是值类型(结构),以及此类型的实例didSet的{​​{1}}属性观察者(在您的{即使您只设置/更新investment的基础属性,也会调用{1}}子类。如果您想避免这种情况,请将UITableViewCell更改为引用类型(类),在这种情况下,investment属性观察器只有在Investment实例本身已设置/更新。

答案 1 :(得分:12)

之所以调用,是因为Investment可能是结构,而不是类。 在Swift中,结构是值类型,而不是类的引用类型。 因此,结构不是“可变的”。

这意味着每当您更改struct属性时,都会分配一个新的struct对象来替换当前的对象,当前的对象数据将被复制到新的对象数据,但更改的属性将包含新的值集。

请记住,每当使用let命令初始化struct对象时,编译器都不允许您更改struct属性(使用类可以执行此操作)。

这解释了为什么每次更改struct属性时都会调用观察者。一旦分配了新的struct对象来替换当前的对象,它现在将存储在另一个内存块中,因此它的值将被更改,并且didSet观察者将被调用。

PS:如果将Investment定义为类而不是结构,则不会发生这种情况。