Swift - Properties
2018-10-23 本文已影响15人
ienos
Support
Classes / Structures / Enumerations
- 计算属性:Classes / Structures / Enumerations
- 存储属性:Classes / Structures
懒加载 -- 初始化值直到第一被使用之前都没有计算
- Usage: 声明前面加 lazy
- Object: 针对于 variable 而言,而不是 constant(因为在初始化完成之前就有值)
- Scene: ① 在初始化完成之后,初始化值需要依赖外部因素 ② 属性复杂,或者需要花费很多时间设置
class DataImporter {
var filename = "data.txt"
}
class DataManager {
// importer 只有第一次使用的时候才会初始化
// 多线程同时访问,将可能不只初始化一次
lazy var importer = DataImporter()
var data = [String]()
}
存储属性 & 实例变量
- OC 中成员变量是定义在 {} 中的变量,如果变量的数据类型是一个类则称这个类为实例变量
- Swift 中不具有实例变量
计算属性
没有存储值,提供一个 getter 和一个可选 setter
struct Size {
var width = 0.0, height = 0.0
}
struct Point {
var x = 0.0, y = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
// 计算属性,不需要存储一个 center 的值
var center: Point {
get {
let centerX = origin.x + (size.width / 2)
let centerY = origin.x + (size.height / 2)
return Point(x: centerX, y: centerY)
}
// 如果没有设置一个新值默认是 newValue
set (newCenter) {
origin.x = newCenter.x - (size.width / 2)
origin.y = newCenter.y - (size.height / 2)
}
}
}
// 只读计算属性
struct Cuboid {
var width = 0.0, height = 0.0, depth = 0.0
var volume: Double {
return width * height * depth
}
}
属性观察者 -- willSet / didSet
- 可以添加属性观察者到任何存储属性,除了懒加载存储属性
- 可以重写一个子类的属性,添加属性观察者到任何继承属性(无论是存储属性还是计算属性)
参数使用
- willSet 传递一个常量 -- 默认变量名: newValue -- 新值
- didSet 传递一个常量 -- 默认变量名: oldValue -- 旧值
调用场景
- 父类属性在子类初始化中设置,在父类初始化之后会被调用
- 当一个类在父类初始化调用之前,设置自己属性不会被调用
- 如果传递一个被观察的属性作为输入输出参数,willSet / didSet 会被调用,值总会在方法结束时写回属性。
全局变量 & 局部变量
- 全局变量:被定义在函数、方法、闭包或者类型上下文外
- 局部变量:被定义在函数、方法、闭包或者类型上下文内
类型属性
- 区别于实例属性,实例属性属于一个实例的属性并区分于其他实例的属性
- 存储类型属性能为变量或者常量,计算类型属性为变量
- 区分于实例属性,需要给定一个默认值,因为类型熟悉没有初始化去分配值
- 存储类型属性在第一次访问是懒加载初始化,且初始化一次,即使在多个线程中同时访问,且不需要使用 lazy 关键字修饰
struct SomeStructure {
static var storedTypeProperty = "Some value."
// 如果需要子类能够重写,在前面加 class 关键字
static var computedTypeProperty: Int {
return 1
}
}
// 访问
SomeStructure.storedTypeProperty
struct AudioChannel {
static let thresholdLevel = 10
// 所有 AudioChannel 实例共享这个变量
static var maxInputLevelForAllChannels = 0
var currentLevel: Int = 0 {
didSet {
if currentLevel > AudioChannel.thresholdLevel {
// 这里不会再调用观察者 set
currentLevel = AudioChannel.thresholdLevel
}
if currentLevel > AudioChannel.maxInputLevelForAllChannels {
AudioChannel.maxInputLevelForAllChannels = currentLevel
}
}
}
}