- 存儲屬性只能用于類和結(jié)構(gòu)體蔓姚,計算屬性可以用于類颤绕,結(jié)構(gòu)體幸海,枚舉。
- 結(jié)構(gòu)體的屬性為var可變 但是如果結(jié)構(gòu)體實例為let不可變得屋厘,則var屬性也不可以修改涕烧,因為結(jié)構(gòu)體是值屬性。
- 必須將延時屬性用var修飾汗洒。
- 計算屬性必須用var修飾议纯,因為值是不固定的。不必糾結(jié)是否像oc中重寫setter一樣保存新值溢谤,因為必有g(shù)et方法瞻凤。
- 屬性觀察器可以為除了延時存儲屬性之外的存儲屬性添加,即使新值和舊值相同也可以觸發(fā)世杀。
- 全局的屬性都是延時計算的阀参,不需要用lazy修飾。
- 類屬性用static修飾瞻坝,需要給一個初始值(因為沒有構(gòu)造方法)
1.存儲屬性
如果結(jié)構(gòu)體的實例為let不可變蛛壳,則其存儲屬性即使是可變的,也無法修改
struct FixedLengthRange {
var firstValue: Int
let length: Int
}
//相當(dāng)于初始化方法,所以可以給不可變得length賦值
let rangeOfThreeItems = FixedLengthRange(firstValue: 2, length: 5)
rangeOfThreeItems.firstValue = 3 //這里是會報錯的
如果結(jié)構(gòu)體的存儲屬性沒有默認(rèn)值衙荐,則在初始化的時候可以設(shè)置let類型的初始值捞挥,否則無法改變。
2.延遲存儲屬性
在被訪問的時候才被創(chuàng)建忧吟。(類似懶加載)
- 如果一個被標(biāo)記為 lazy 的屬性在沒有初始化時就同時被多個線程訪問砌函,則無法保證該屬性只會被初始化一次。
class DataImporter {
var filename = "data.text"
}
class DataManager {
var data = [String]()
lazy var importer = DataManager()
}
let manager = DataManager()
manager.data.append("zc")
manager.data.append("cz")
print(manager.importer.data) //此時importer屬性才被創(chuàng)建
3.計算屬性
struct Point {
var x = 0.0,y = 0.0
}
struct Size {
var width = 0.0,height = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
var center :Point {
get {
let centerX = origin.x + size.width/2
let centerY = origin.y + size.height/2
return Point(x: centerX, y: centerY)
}
set(newCenter){
origin.x = newCenter.x - size.width/2
origin.y = newCenter.y - size.height/2
}
}
}
如果set(newCenter)改為set ,則默認(rèn)使用newValue表示溜族。
只讀計算屬性:只能獲取讹俊,不能設(shè)置,但是仍然要用var修飾,因為他不是固定不變的煌抒。
struct Cuboid {
var width = 0.0, height = 0.0, depth = 0.0
var volume: Double {
return width * height * depth
}
}
4.屬性觀察器
當(dāng)屬性被設(shè)置時會觸發(fā)哪怕值不變化仍劈。(默認(rèn)參數(shù)為newValue和oldValue)
class StepCounter {
var totalSteps : Int = 0 {
willSet(newValue){
print(newValue)
}
didSet(oldValue){
print(oldValue)
}
}
}
4.類型屬性
類型屬性相當(dāng)于類屬性,只有類對象可以直接改變他的值和獲取它的值寡壮。
struct AudioChannel {
static let thresholdLevel = 10
static var maxInputLevelForAllChannels = 0
var currentLevel: Int = 0 {
didSet {
if currentLevel > AudioChannel.thresholdLevel {
// 將當(dāng)前音量限制在閾值之內(nèi)
currentLevel = AudioChannel.thresholdLevel
}
if currentLevel > AudioChannel.maxInputLevelForAllChannels {
// 存儲當(dāng)前音量作為新的最大輸入音量
AudioChannel.maxInputLevelForAllChannels = currentLevel
}
}
}
}
///打印值為7
var left = AudioChannel()
left.currentLevel = 6
AudioChannel.maxInputLevelForAllChannels = 7
print(AudioChannel.maxInputLevelForAllChannels)