「这是我参与2022首次更文挑战的第13天,活动详情查看:2022首次更文挑战」。
使用方式:
- 1、类中定义的存储属性
- 2、通过类继承的存储属性
class HJBoy : HJPerson{
override var age: Int{
//新值存储之前调用
willSet{
print("willSet newValue (newValue)")
}
//新值存储之后调用
didSet{
print("didSet oldValue (oldValue)")
}
}
}
- 3、通过类继承的计算属性
class HJPerson{
var age: Int = 18
var age2: Int {
get{
return age
}
set{
self.age = newValue
}
}
}
var t = HJPerson()
class HJBoy : HJPerson{
override var age: Int{
//新值存储之前调用
willSet{
print("willSet newValue (newValue)")
}
//新值存储之后调用
didSet{
print("didSet oldValue (oldValue)")
}
}
override var age2: Int{
//新值存储之前调用
willSet{
print("willSet newValue (newValue)")
}
//新值存储之后调用
didSet{
print("didSet oldValue (oldValue)")
}
}
}
属性观察者的触发时机:
以下代码中,init方法中设置name,是否会触发属性观察者?
class HJPerson{
var name: String = "测试"{
//新值存储之前调用
willSet{
print("willSet newValue (newValue)")
}
//新值存储之后调用
didSet{
print("didSet oldValue (oldValue)")
}
}
init() {
self.name = "KC"
}
}
运行结果发现,并没有走willSet、didSet中的打印方法,所以有以下结论:
- 在init方法中,如果调用属性,是不会触发属性观察者的
- init中主要是初始化当前变量,除了默认的前16个字节,其他属性会调用
memset清理内存空间(因为有可能是脏数据,即被别人用过),然后才会赋值
【总结】:初始化器(即init方法设置)和定义时设置默认值(即在didSet中调用其他属性值)都不会触发
【问题1】:子类和父类的计算属性同时存在didset、willset时,其调用顺序是什么?
import Foundation
class HJPerson {
var age: Int = 18{
//新值存储之前调用
willSet{
print("父类 willSet newValue (newValue)")
}
//新值存储之后调用
didSet{
print("父类 didSet oldValue (oldValue)")
}
}
var age2: Int {
get{
return age
}
set{
self.age = newValue
}
}
}
class HJSon: HJPerson{
override var age: Int{
//新值存储之前调用
willSet{
print("子类 newValue (newValue)")
}
//新值存储之后调用
didSet{
print("子类 didSet oldValue (oldValue)")
}
}
}
var t = HJSon()
t.age = 20
// ------打印:
子类 newValue 20
父类 willSet newValue 20
父类 didSet oldValue 18
子类 didSet oldValue 18
【结论】:对于同一个属性,子类和父类都有属性观察者,其顺序是:先子类willset,后父类willset,再父类didset, 子类的didset,即:子父 父子,记忆:父总是让着子
【问题2】:子类调用了父类的init,是否会触发观察属性?
import Foundation
class HJPerson {
var age: Int = 18{
//新值存储之前调用
willSet{
print("父类 willSet newValue (newValue)")
}
//新值存储之后调用
didSet{
print("父类 didSet oldValue (oldValue)")
}
}
var age2: Int {
get{
return age
}
set{
self.age = newValue
}
}
}
class HJSon: HJPerson{
override var age: Int{
//新值存储之前调用
willSet{
print("子类 newValue (newValue)")
}
//新值存储之后调用
didSet{
print("子类 didSet oldValue (oldValue)")
}
}
override init() {
super.init()
self.age = 20
}
}
//****** 打印结果 ******
子类 willSet newValue 20
父类 willSet newValue 20
父类 didSet oldValue 18
子类 didSet oldValue 18
- 从打印结果发现,会触发属性观察者,主要是因为子类调用了父类的init,已经初始化过了,而初始化流程保证了所有属性都有值(即super.init确保变量初始化完成了),所以可以观察属性了
三、 类型属性
- 1、使用关键字
static修饰,且是一个全局变量 - 2、类型属性
必须有一个默认的初始值 - 3、类型属性只会被
初始化一次
举例:
class CJLTeacher{
static var age: Int = 18
}
// **** 使用 ****
var age = CJLTeacher.age