- 屬性有存儲屬性,計算屬性
- 存儲屬性包括常量存儲屬性,變量存儲屬性
- 常量存儲屬性特性
- 若是一個值類型變量被聲明爲let,那麼這個變量下的全部都是常量不能夠改。
- 若是是一個引用類型被定義爲let,那麼這個類型下的常量不可改變,變量依然能夠改變。
struct Size {
var a = 0
}
class React {
var area = 0.0
}
let size = Size(a: 4)
size.a = 2
let react = React()
react.area = 3
react.area = 5
複製代碼
- 延時存儲屬性
- 當一個屬性加載大量數據,而且它可能用到,也可能用不到,這時候推薦使用延時存儲屬性
- 延時存儲屬性必定是var類型
class DataImport {
var fileName = "file.txt"
}
class DataManger {
lazy var importer = DataImport()
var data = [String?]()
}
let dataManager = DataManger()
dataManager.data.append("one.txt")
dataManager.data.append("two.txt")
print(dataManager.importer.fileName)
複製代碼
- swift屬性沒有實例變量,它的變量就是屬性。
- 計算屬性
- 若是這個屬性是靠其餘屬性計算得來的,那麼這個屬性應該用計算屬性。
- 計算屬性要用var類型和延時存儲屬性同樣都用var。
- 以後寫好計算屬性名字後邊要寫上類型,以後大括號。
- 必需要有一個get方法,用來返回這個計算屬性的計算結果。
- 能夠有一個可選的set方法,該方法內部能夠用newValue來省略參數。
- 在用構造器初始化屬性時候,實際上是在初始化存儲屬性,計算屬性不用初始化,由於他能夠用存儲屬性計算得來。
- 在使用時候只要給相關的存儲屬性賦值後,計算屬性就能夠計算得來。
- 在使用時候只要給計算屬性賦值了,那麼就能夠得出新的存儲屬性.
struct Point {
var x = 0.0, y = 0.0
}
struct Size {
var width = 0.0, height = 0.0
}
struct React {
var origin = Point()
var size = Size()
var center: Point {
get{
let x = origin.x + (size.width/2.0)
let y = origin.y + (size.height/2.0)
return Point(x: x, y: y)
}
set{
origin.x = newValue.x - (size.width/2.0)
origin.y = newValue.y - (size.height/2.0)
}
}
}
var react = React(origin: Point(x: 0.0, y: 0.0), size: Size(width: 20, height: 10))
print(react.center)
react.center = Point(x: 30, y: 40)
print(react.origin)
複製代碼
- 只讀計算屬性
- 首先該屬性是用其餘存儲屬性計算獲得的,肯定該屬性是計算屬性。
- var name:type{}
- 肯定該計算屬性有沒有setter方法
- 若是沒有setter方法,那就是隻讀計算屬性,這時候能夠直接省略get關鍵字。
- 若是有seeter方法,那就是可讀寫計算屬性,get關鍵字不能夠省略,set能夠省略參數。
struct Cuboid {
var width = 0.0, height = 0.9, depth = 0.0
var volume: Double {
return width * height * depth
}
}
var cuboid = Cuboid(width: 10, height: 10, depth: 5)
print("volume: \(cuboid.volume)")
cuboid.width = 20
print("volume: \(cuboid.volume)")
複製代碼
- 屬性觀察器
- 若是要觀察計算屬性的賦值變化就添加set方法。
- 若是要觀察存儲屬性的賦值變化能夠用屬性觀察器。
- 因此通常屬性觀察器用在存儲屬性上。
- willSet能夠取到newValue,didSet能夠取到oldValue
class StepCounter {
var totalStep = 0 {
willSet{
print("willSet --- 新值:\(newValue) 舊值:\(totalStep)")
}
didSet{
print("didSet --- 新值:\(totalStep) 舊值:\(oldValue)")
}
}
}
var step = StepCounter()
step.totalStep = 100
step.totalStep = 300
step.totalStep = 800
//打印以下
//willSet --- 新值:100 舊值:0
//didSet --- 新值:100 舊值:0
//willSet --- 新值:300 舊值:100
//didSet --- 新值:300 舊值:100
//willSet --- 新值:800 舊值:300
//didSet --- 新值:800 舊值:300
複製代碼
- 屬性觀察器變量若是傳入一個inout類型函數的參數中,即便函數內部沒有操做。也會觸發屬性觀察器。
class StepCounter {
var totalStep = 0 {
willSet{
print("willSet --- 新值:\(newValue) 舊值:\(totalStep)")
}
didSet{
print("didSet --- 新值:\(totalStep) 舊值:\(oldValue)")
}
}
}
var step = StepCounter()
func test(a: inout Int){
}
test(a: &step.totalStep)
複製代碼
- 全局變量和局部變量
- 全局變量都是延時變量,用到時候纔會加載。
- 局部變量必定不是延時變量,也不容許寫lazy關鍵字。
- 類外就是全局變量。類內是屬性,方法閉包內部是局部變量。
//全局變量
var globleVar = 4.5
class Test {
//屬性
var a = 1
init() {
//局部變量
var b = 2
}
}
複製代碼
- 類型屬性
- 若是一個屬性被全部實例對象共享那就考慮用類型屬性
- 類型屬性關鍵字是static,它是用類訪問的變量。和類有關
- 實例屬性是實例訪問的屬性,和實例有關
struct AudioChannel {
static let thresholdLevel = 10
static var maxLevelForAllChannel = 0
var curLevel = 0{
didSet{
if curLevel > AudioChannel.thresholdLevel {
curLevel = AudioChannel.thresholdLevel
}
if curLevel > AudioChannel.maxLevelForAllChannel {
AudioChannel.maxLevelForAllChannel = curLevel
}
}
}
}
var leftAudioChannel = AudioChannel(curLevel: 0)
var rightAudioChannel = AudioChannel(curLevel: 0)
leftAudioChannel.curLevel = 2
print(AudioChannel.maxLevelForAllChannel)
rightAudioChannel.curLevel = 3
print(AudioChannel.maxLevelForAllChannel)
rightAudioChannel.curLevel = 13
print(AudioChannel.maxLevelForAllChannel)
複製代碼
- 總結
- 類外是全局變量 - 延時加載
- 類內是屬性
- 屬性包括實例屬性和類型屬性
- 存儲屬性
- 常量存儲屬性
- 變量存儲屬性
- 延時存儲屬性
- 屬性觀察器
- 計算屬性
- 函數閉包內部是局部變量 - 必定不是延時加載的,也不容許用lazy關鍵字