本文首發於個人我的博客html
這篇文章分享一下Swift中的屬性github
關於這個規定,咱們在Swift之結構體 一文中已經說過了,這裏稍微提一下,好比下面代碼,x和y都是存儲屬性,當初始化的時候,若是沒值,編譯器會直接報錯。編程
struct Point{
var x: Int
var y: Int
}
var p1 = Point(x: 10, y: 20)
var p2 = Point(y: 20) //報錯 Missing argument for parameter 'x' in call
var p3 = Point(x: 10) //報錯 Missing argument for parameter 'y' in call
var p4 = Point() //報錯 Missing argument for parameter 'x' in call
複製代碼
以下面結構體Circle
包括了存儲屬性radius
和計算屬性diameter
swift
truct Circle {
// 存儲屬性
var radius: Double
// 計算屬性
var diameter: Double {
set {
radius = newValue / 2
}
get {
return radius * 2
}
}
}
var circle = Circle(radius: 5)
print(circle.radius) // 5.0
print(circle.diameter) // 10.0
circle.diameter = 12
print(circle.radius) // 6.0
print(circle.diameter) // 12.0
複製代碼
struct Circle {
var radius: Double
var diameter: Double {
get {
radius * 2
}
}
}
複製代碼
只讀計算屬性能夠簡寫,例如上面的代碼能夠以下表示安全
struct Circle {
var radius: Double
var diameter: Double { radius * 2 }
}
複製代碼
關於不佔用實例的內存,能夠以下代碼證實bash
struct Circle {
// 存儲屬性
var radius: Double
// 計算屬性
var diameter: Double {
set {
radius = newValue / 2
}
get {
return radius * 2
}
}
}
print("Double佔用字節", MemoryLayout<Double>.stride)
print("Circle佔用字節",MemoryLayout<Circle>.stride) // 8
複製代碼
輸出爲app
Double佔用字節 8
Circle佔用字節 8
複製代碼
也就是說Circle
佔用的僅僅是其存儲屬性radius
所佔用的內存。和計算屬性無關的,讀者也能夠多寫幾個計算屬性,自行驗證。ide
代碼以下函數
struct Circle {
// 存儲屬性
var radius: Int
// 計算屬性
var diameter: Int {
set {
radius = newValue / 2
}
get {
return radius * 2
}
}
}
var circle = Circle(radius: 9)
circle.radius = 5
circle.diameter = 8 //這裏打斷點
複製代碼
5存儲到了全局變量0x3e96(%rip)
,全局變量只有circle
,因此也就是說存儲屬性的值,被直接放在告終構體的內存中。
8賦值給寄存器%r8d
,又給寄存器%edi,做爲參數調用函數0x100001ae0
的時候傳入,而函數0x100001ae0
就是testSwift.Circle.diameter.setter
這就是存儲屬性和計算屬性的區別
在Swift枚舉一文中,咱們說過枚舉原始值是不佔用內存的。
enum Season: Int{
case test1 = 1, test2, test3, test4
}
var s = Season.test2
print(s.rawValue) //輸出2
複製代碼
上面代碼輸出爲2。 這些原始值 test1 = 1, test2, test3, test4,系統內部徹底能夠寫成只讀計算屬性
enum Season: Int{
case test1 = 1, test2, test3, test4
var rawValue : Int {
switch self {
case .test1:
return 11
case .test2:
return 12
case .test3:
return 13
case .test4:
return 14
}
}
}
var s = Season.test2
print(s.rawValue) //輸出12
複製代碼
上面代碼輸出爲12,這樣就完成了獲取枚舉的原始值的時候,直接獲取的是隻讀計算屬性。光看結果是不夠使人信服的,那就看彙編
enum Season: Int{
case test1 = 1, test2, test3, test4
}
var s = Season.test2
print(s.rawValue) //這裏打斷點
複製代碼
上述代碼在最後一行打斷點
能夠看到,確實調用了rawValue.getter
。
因此彙編纔是看出本質的神器。
eg:有類 Car和類Person ,car做爲Person的延遲存儲屬性,那麼當使用car的是,纔會調用car的初始化方法。
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!
Car is running!
複製代碼
struct Circle {
var radius: Double {
willSet {
print("willSet", newValue)
}
didSet {
print("didSet", oldValue, radius)
}
}
init() {
self.radius = 1.0
print("Circle init!")
}
}
var circle = Circle()// 輸出 Circle init!
circle.radius = 10.5
// 輸出 willSet 10.5
// didSet 1.0 10.5
print(circle.radius) //輸出 10.5
複製代碼
eg:
var num: Int {
get {
return 10
}
set {
print("setNum", newValue)
}
}
num = 11 // setNum 11
print(num) // 10
func test() {
var age = 10 {
willSet {
print("willSet", newValue)
}
didSet {
print("didSet", oldValue, age)
}
}
age = 11
// willSet 11
// didSet 10 11
}
test()
複製代碼
eg:
struct Car {
static var count: Int = 0
init() {
Car.count += 1
}
}
let c1 = Car()
let c2 = Car()
let c3 = Car()
print(Car.count) // 輸出3
複製代碼
關於單例模式,能夠參考個人另外一篇文章你真的懂單例模式麼
不一樣語言的單例模式,都是相似的,這裏給出Swift版本單例的實現。
import Foundation
public class FileManager {
//單例模式
public static let shared = FileManager()
private init() { }
}
// 若是單例裏面代碼過多,能夠寫成以下
public class FileManager {
public static let shared = {
// ....
// ....
return FileManager()
}()
private init() { }
}
複製代碼
下面的代碼
import Foundation
public class YZPerson {
static var count = 3 //這裏打斷點
}
YZPerson.count = 6
複製代碼
以下圖所示,能夠看出,會調用 swift_once
函數,來到這個調用位置,si彙編調試指令,一直跟進去
最終會來到這裏,調用dispatch_once_f
也就是說static
內部封裝了dispatch_once_
而dispatch_once_
能保證線程安全的,只能被初始化一次,因此單例的時候能夠用static
關於 dispatch_once
的分析,能夠看這篇文章你真的懂單例模式麼
static
修飾的變量,屬於全局變量。讀者有興趣本身證實。這裏再也不贅述。參考資料:
更多資料,歡迎關注我的公衆號,不定時分享各類技術文章。