Swift中熟悉的陌生人:Protocol(一)

本文算是我對Swift基礎知識的一個再梳理蝗岖,不會再討論基礎語法,而是把一些文檔之外的東西架曹,進行一次再梳理總結隘冲,方便查閱。

我們這里首先來做一個分析音瓷,一個是普通的String對象对嚼,一個是遵守協議的String對象夹抗,這里我們來對比一下它們各自占用多大的內存绳慎?
這里先羅列一下實驗的協議和擴展代碼:

protocol TestProtocol { 
    var testData:NSURL? {get}
}

extension String:TestProtocol{
    var testData:NSURL? {
        return NSURL()
    }
}

然后我們開始書寫下面的測試代碼:

var qurl:TestProtocol = "123"
print(MemoryLayout<TestProtocol>.size)  //40
var string:String = "123"
print(MemoryLayout<String>.size)    //24

我們可以在playground中看到結果,遵守protocol的qurl的大小為40漠烧,而不遵守任何協議的string的大小為24.
在Swift中杏愤,由于string是stuct結構體,而不再是OC中的class已脓,所以不再是8個字節(jié)珊楼,24個字節(jié)的結構也可以用LLDB動態(tài)調試type lookup String來查看
,最后我們發(fā)現

 var _baseAddress: Swift.UnsafeMutableRawPointer?
 var _countAndFlags: Swift.UInt
 var _owner: AnyObject?

這三個屬性每個大小為8個字節(jié)度液,加起來就是24字節(jié)厕宗,那么協議對象的40字節(jié)又該如何解釋呢?
這里我們首先查看對象的地址堕担,這里我們首先寫一個打印地址的函數

func addrOf<T>( v:inout T){
  withUnsafePointer(to: &v) { print($0)}
}

addrOf(v: &qurl)

最后我這里打印出結果已慢,地址為0x00000001003dfb20
然后我們實用LLDB的動態(tài)調試指令:x/5xg 0x00000001003dfb20
查看其5個字長的內存空間
得出結果

0x1003dfb20: 0x00000001003397f8 0x0000000000000003
0x1003dfb30: 0x0000000000000000 0x00000001003ad878
0x1003dfb40: 0x000000010038a548

這里繼續(xù)使用image lookup -a 0x00000001003397f8查看第一個地址
我們可以發(fā)現值為

Address: SwiftTest[0x00000001003397f8] (SwiftTest.__TEXT.__cstring + 72)
      Summary: "123"

這第一個值其實存放的是遵守協議的字符串的值,我們可以發(fā)現它是cstring
第二個存放字符個數和第三個地址為0霹购,這兩個我們不管佑惠,直接解析第4個和第5個地址的內容。

image lookup -a 0x00000001003ad878
      Address: SwiftTest[0x00000001003ad878] (SwiftTest.__DATA.__const + 144264)
      Summary: SwiftTest`type metadata for Swift.String

我們可以發(fā)現第四個地址存放的是type metadata,即類型元數據膜楷,類型元數據即描述類的數據旭咽,有點類似Objective-C中的元類的作用

image lookup -a 0x000000010038a548
      Address: SwiftTest[0x000000010038a548] (SwiftTest.__DATA.__const + 88)
      Summary: SwiftTest`protocol witness table for Swift.String : SwiftTest.TestProtocol in SwiftTest

而第5個地址打印出味protocol witness table,即協議見證表赌厅,這個概念非常類似與Cpp中的vtable穷绵,即虛函數表。
那么什么是虛函數表呢特愿?

6A8C58DD-4C1E-4DD4-B860-09DC27890748.png

在Swift请垛,不同的結構、枚舉洽议、類都可以繼承協議,同樣的url屬性就會產生不同的getter方法宗收。就像這張Cpp中的虛函數表一樣,不同vfunc1可能有不同的實現函數地址亚兄,所以需要有一個虛函數表來維護混稽。
這里我們繼續(xù)試驗:
我們發(fā)現第5個地址即指向虛函數表的地址,那個根據如圖所示审胚,其實我們可以繼續(xù)解析這個虛函數表的地址的內存匈勋,繼續(xù)使用

x/xg 0x000000010038a548
0x10038a548: 0x0000000100002470

我們再看看看看這個虛函數表存放的地址的指令

x/i 0x0000000100002470
    0x100002470: 55  pushq  %rbp

看到pushq %rbp(這句表示:將調用函數的棧底壓棧到被調函數的棧中),我們就應該猜到這個地址存放了一個函數膳叨。
于是使用

image lookup -a 0x0000000100002470
     Address: SwiftTest[0x0000000100002470] (SwiftTest.__TEXT.__text + 2608)
     Summary: SwiftTest`protocol witness for SwiftTest.TestProtocol.testData.getter : Swift.Optional<__ObjC.NSURL> in conformance Swift.String : SwiftTest.TestProtocol in SwiftTest at TestDataConvertible.swift

我們就能發(fā)現在該支持實際存放了一個testData.getter方法洽洁。

D49A102E-CA5C-46C6-8FCB-853A3CA9E4C5.png

如果有多個對象,那么就會變成這樣的結構:

542180AA-B179-4861-A80D-BA02413CC2CE.png

通過這樣的結構菲嘴,也說明了為什么協議只能存儲計算屬性而不能存儲 存儲屬性饿自,這就是我對協議的理解,有更多關于協議的有趣內容龄坪,歡迎下方留言昭雌,與我分享。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末健田,一起剝皮案震驚了整個濱河市烛卧,隨后出現的幾起案子,更是在濱河造成了極大的恐慌妓局,老刑警劉巖总放,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異好爬,居然都是意外死亡局雄,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門抵拘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來哎榴,“玉大人型豁,你說我怎么就攤上這事∩序颍” “怎么了迎变?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長飘言。 經常有香客問我衣形,道長,這世上最難降的妖魔是什么姿鸿? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任谆吴,我火速辦了婚禮,結果婚禮上苛预,老公的妹妹穿的比我還像新娘句狼。我一直安慰自己,他們只是感情好热某,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布腻菇。 她就那樣靜靜地躺著,像睡著了一般昔馋。 火紅的嫁衣襯著肌膚如雪筹吐。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天秘遏,我揣著相機與錄音丘薛,去河邊找鬼。 笑死邦危,一個胖子當著我的面吹牛洋侨,可吹牛的內容都是我干的。 我是一名探鬼主播铡俐,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼凰兑,長吁一口氣:“原來是場噩夢啊……” “哼妥粟!你這毒婦竟也來了审丘?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤勾给,失蹤者是張志新(化名)和其女友劉穎滩报,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體播急,經...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡脓钾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了桩警。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片可训。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出握截,到底是詐尸還是另有隱情飞崖,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布谨胞,位于F島的核電站固歪,受9級特大地震影響,放射性物質發(fā)生泄漏胯努。R本人自食惡果不足惜牢裳,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望叶沛。 院中可真熱鬧蒲讯,春花似錦、人聲如沸灰署。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽氓侧。三九已至脊另,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間约巷,已是汗流浹背偎痛。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留独郎,地道東北人踩麦。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像氓癌,于是被迫代替她去往敵國和親谓谦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內容