1. 程式人生 > Android開發 >Swift Runtime(1)-初探

Swift Runtime(1)-初探

#前言 本文介紹Swift Runtime機制.相信大家對於Objective-C裡的Class都或多或少有一些瞭解.即使沒有去研究過,也可能聽說過Class其實是結構體,結構體裡面含有isa,superClass這樣的說法.那麼本文研究的就是Swift類本質及其執行時原理.

#初探 首先新建一個Xcode專案,為了不讓其它因素幹擾,選擇Command Line Tool

新建Command Line Tool

生成專案的目錄結構非常簡單

目錄結構
先進入main.swift檔案檢視.可以看到檔案內容非常簡單,這就是選擇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三個變數成功賦值了.

讓我們仔細的看一下三個變數,可以看出都是Person類,後面的16進位制值其實是變數所指向的地址,a,c三個變數其實是三個指向Person類的指標,而他們的值就是Person類的例項物件所在的地址.
那麼讓我們來看一下物件所在的地址裡都是什麼內容.在lldb輸入如下命令: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!") 複製程式碼

明顯發現a,c三個Person型別的起始位置為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結構體,並且儲存類資訊和自己的引用計數.接下來我們就會仔細研究一下這兩個metadatarefCounts.

Swift Runtime(2)-引用計數