加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

swift学习日志—— 属性观察

发布时间:2020-12-14 01:31:09 所属栏目:百科 来源:网络整理
导读:属性观察 (Property Observers) 是 Swift 中一个很特殊的特性,利用属性观察我们可以在当前类型内监视对于属性的设定,并作出一些响应。Swift 中为我们提供了两个属性观察的方法,它们分别是 willSet 和 didSet 。 使用这两个方法十分简单,我们只要在属性声

属性观察 (Property Observers) 是 Swift 中一个很特殊的特性,利用属性观察我们可以在当前类型内监视对于属性的设定,并作出一些响应。Swift 中为我们提供了两个属性观察的方法,它们分别是willSetdidSet

使用这两个方法十分简单,我们只要在属性声明的时候添加相应的代码块,就可以对将要设定的值和已经设置的值进行监听了:

class MyClass {

let oneYearInSecond:NSTimeInterval = 365 * 24 * 60 * 60

var date:NSDate{

willSet {

print("即将将日期从 (date) 设定至 (newValue)")

}

didSet{

if date.timeIntervalSinceNow > oneYearInSecond{

print("设定时间太晚了")

date = NSDate().dateByAddingTimeInterval(oneYearInSecond + 800000)

//这里让设置值依然大于oneYearInSecond,不会再次触发属性观察的调用(即不会陷入死循环)

}

print("已经将日期从 (oldValue) 设定至 (date)")

}

}

init(){

date = NSDate()

}

}

let fo = MyClass()

fo.date = fo.date.dateByAddingTimeInterval(60_000_000)


Log:

即将将日期从 2015-12-29 06:06:13 +0000 设定至 2017-11-22 16:46:13 +0000

设定时间太晚了

已经将日期从 2015-12-29 06:06:13 +0000 设定至 2017-01-06 12:19:33 +0000


A>初始化方法对属性的设定,以及在willSetdidSetA>对属性的再次设定都不会再次触发属性观察的调用,放心吧。


在 Swift 中所声明的属性包括存储属性和计算属性两种。其中存储属性将会在内存中实际分配地址对属性进行存储,而计算属性则不包括背后的存储,只是提供setget两种方法。在同一个类型中,属性观察和计算属性是不能同时共存的。也就是说,想在一个属性定义中同时出现是一件办不到的事情。计算属性中我们可以通过改写中的内容来达到和同样的属性观察的目的。如果我们无法改动这个类,又想要通过属性观察做一些事情的话,可能就需要子类化这个类,并且重写它的属性了。重写的属性并不知道父类属性的具体实现情况,而只从父类属性中继承名字和类型,因此在子类的重载属性中我们是可以对父类的属性任意地添加属性观察的,而不用在意父类中到底是存储属性还是计算属性:

class A {

var name:String = "jack" //存储属性

var age :Int { //计算属性

get{

print("get")

return 1

}

set{

print("set")

}

}

}


class B: A {

override var age:Int{ //子类都可以设置属性观测器

willSet{

print("age--willSet")

}

didSet{

print("age--didSet")

}

}

override var name:String{ //子类都可以设置属性观测器

willSet{

print("name--willSet")

}

didSet{

print("name--didSet")

}

}

}



调用 name和ageset方法可以看到工作的顺序

let b = B()

b.age = 0

b.name = "Tom"



Log:

get

age--willSet

set

age--didSet

name--willSet

name--didSet


和对应的属性观察的调用都在我们的预想之中。这里要注意的是首先被调用了一次。这是因为我们实现了中会用到oldValue,而这个值需要在整个动作之前进行获取并存储待用,否则将无法确保正确性。如果我们不实现的话,这次操作也将不存在。

class A {

var name:String = "jack" //存储属性

var age :Int { //计算属性

get{

print("get")

return 1

}

set{

print("set")

}

}

}


class B: A {

override var age:Int{ //子类都可以设置属性观测器

willSet{

print("age--willSet")

}

// didSet{

// print("age--didSet")

// }

}

override var name:String{ //子类都可以设置属性观测器

willSet{

print("name--willSet")

}

didSet{

print("name--didSet")

}

}

}


let b = B()

b.age = 0

b.name = "Tom"


Log成这样了:

age--willSet

set

name--willSet

name--didSet

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读