swift中跟实例相关的属性可以分为两大类:
* 存储属性
- 类似于成员变量这个概念
- 存储在实例的内存中
- 结构体、类可以定义存储属性
- 枚举不可以定义存储属性
关于枚举为什么不能定义存储属性:
enum textEnum{
case text1,text2
}
var p = textEnum.text1
//内存中会拿出一个字节存储 p
enum textEnum1{
case text1(Int),text2(Double)
}
var p1 = textEnum1.text1(20)
//枚举内存中会有8个字节存储关联属性
enum textEnum2: Int{
var x: Int //错误的
case text1 = 10,text2 = 20
}
var p2 = textEnum2.text1
//内存中会拿出一个字节存储 p2,当你在枚举中写道 var x: Int ,貌似是顶一个一个存储属性,但是不会将 var x: Int的内存放到枚举中
在创建类 或 结构体的实例时,必须为所有的存储属性设置一个合适的初始值
- 可以在初始化器里为存储属性设置一个初始值
- 可以分配一个默认的属性值作为属性定义的一部分
* 计算属性
- 本质就是方法(函数)
- 计算属性的特点是不占用实例的内存
- 枚举、结构体、类都可以定义计算属性
set传入的新值默认叫做newValue,也可以自定义,例如定义为:newDiameter
struct Circle {
var radius: Double
var diameter: Double {
set(newDiameter) {
radius = newDiameter / 2
}
//set不写()的话,默认为newValue
//set{
// radius = newValue / 2
// }
get {
radius * 2 }
}
}
只读计算属性:只有get,没有set
struct Circle {
var radius: Double
var diameter: Double {
get {
radius * 2
}
}
}
延迟存储属性(Lazy Stored Property)
使用lazy可以定义一个延迟存储属性,在第一次用到属性的时候才会进行初始化
class Car {
init() {
print("Car init!")
}
func run() {
print("Car is running!")
}
}
class Person {
lazy var car = Car()
init() {
print("Person init!")
}
func goOut() {
car.run()
}
}
let p = Person()
print("--------")
p.goOut()
打印结果为:
Person init!
--------
Car init!
当在Person中定义car的时候,前面加 lazy,表明car为延迟属性,当let p = Person()的时候,不会对car进行初始化操作,但是当p.goOut()的时候,goOut()方法中用到了Car,此时对car进行了初始化操作。
应用实例:
class PhotoView {
lazy var image: Image = {
let url = "https://www.520it.com/xx.png"
let data = Data(url: url)
return Image(data: data)
}()
}
var photo = PhotoView()
photo.image
- lazy属性必须是var,不能是let(let必须在实例的初始化方法完成之前就拥有值)
- 如果多条线程同时第一次访问lazy属性 ,无法保证属性只被初始化1次
-
当结构体包含一个延迟存储属性时,只有var才能访问延迟存储属性 ,因为延迟属性初始化时需要改变结构体的内存
例如:
image.png
属性观察器(Property Observer)
可以为 设置属性观察器,不能为计算属性添加属性观察器
struct Circle {
var radius: Double {
//属性的值将要改变,newValue是将要改变的值
willSet {
print("willSet", newValue)
}
//属性的值已经改变,oldValue是改变之前的值
didSet {
print("didSet", oldValue, radius)
}
}
init() {
self.radius = 1.0
print("Circle init!")
}
}
// Circle init!
var circle = Circle()
// willSet 10.5
// didSet 1.0 10.5
circle.radius = 10.5
// 10.5
print(circle.radius)
- willSet会传递新值,默认叫newValue
- didSet会传递旧值,默认叫oldValue
- 在初始化器中设置属性值不会触发willSet和didSet ,在属性定义时设置初始值也不会触发willSet和didSet
如果有什么不对的地方,欢迎指正,大家共同进步!
网友评论