Swift Runtime(1)-初探
阿新 • 來源:網路 • 發佈:2020-06-24
#前言 本文介紹Swift Runtime機制.相信大家對於Objective-C裡的Class都或多或少有一些瞭解.即使沒有去研究過,也可能聽說過Class其實是結構體,結構體裡面含有isa,superClass這樣的說法.那麼本文研究的就是Swift類本質及其執行時原理.
#初探 首先新建一個Xcode專案,為了不讓其它因素幹擾,選擇Command Line Tool
生成專案的目錄結構非常簡單
// main.swift
// Runtime
//
// Created by XXX on 2020/4/19.
// Copyright © 2020 Runtime. All rights reserved.
//
import Foundation
print("Hello,World!")
複製程式碼
接下來刪掉除print("Hello,World")之外包括註釋的所有程式碼,並在print("Hello,World")加上斷點
接下來我們定義一個Person類,並且增加如下程式碼到print("Hello,World")上方:
class Person {
}
var a = Person()
var b = Person()
var c = Person()
print("Hello,World!")
複製程式碼
然後讓我們執行,因為斷點的原因,程式會在print("Hello,World")停住.可以看到a,b,c三個變數成功賦值了.
x/2gx <物件地址>
0x0000000100002108,發現三個物件起始位置都是一樣的,讓人猜測是否是指明型別的資料.我們再來定義一個Animal型別驗證一下:
class Person {
}
class animal {
}
var a = Person()
var b = Person()
var c = Person()
var d = animal()
var e = animal()
var f = animal()
print("Hello,World!")
複製程式碼
0x0000000100002198,而d,e,f三個都為0x0000000100002228與Person類的變數是不一樣的.相同型別的一樣,不同型別的不一樣,可以判斷起始位置就是類資訊資料所在處.
那至於後面一段內容0x0000000400000002,0x0000000200000002是什麼呢?讓我們繼續探究,將程式碼修改成如下,並像上面一樣列印物件內容:
class Person {
}
var a = Person()
print("Hello,World!")
複製程式碼
var b = a,並再次輸出物件內容:
class Person {
}
var a = Person()
var b = a
print("Hello,World!")
複製程式碼
var c = a,並再次輸出物件內容:
class Person {
}
var a = Person()
var b = a
var c = a
print("Hello,World!")
複製程式碼
0x0000000200000002->0x0000000400000002->0x0000000600000002,會發現有一個值會每次有規律的增加2.
而兩次增加的程式碼var b = a var c = a其實是對a變數的引用,每引用一次物件第二段的內容的某個值會增加2.這個看上去是不是很像我們熟悉的引用計數呢?
#總結
其實查閱Swift的原始碼及檔案,一個物件實際上是HeapObject結構體,結構如下:
struct HeapObject {
/// This is always a valid pointer to a metadata object.
HeapMetadata const *metadata;
InlineRefCounts refCounts
}
複製程式碼
其中metadata是描述型別資訊的資料結構指標,而refCounts如名稱所示,是引用計數的資料結構.
所以我們的初步研究完全能得到對應的結果,例項變數是HeapObject結構體,並且儲存類資訊和自己的引用計數.接下來我們就會仔細研究一下這兩個metadata和refCounts.
