iOS開發之runtime(一):runtime除錯環境搭建

kyson老師發表於2019-03-04

本系列部落格是本人的原始碼閱讀筆記,如果有iOS開發者在看runtime的,歡迎大家多多交流。為了方便討論,本人新建了一個微信群(iOS技術討論群),想要加入的,請新增本人微信:zhujinhui207407,【加我前請備註:ios 】,本人部落格http://www.kyson.cn 也在不停的更新中,歡迎一起討論

runtime logo

引言

相信接觸過iOS的同學對runtime或多或少都有耳聞。 建立一個物件:

    [[NSObject alloc] init];
複製程式碼

點選進入其定義:

iOS開發之runtime(一):runtime除錯環境搭建

可以發現其進入了檔案NSObject.h

NSObject

右擊該檔案,選擇:show in Finder可以看到runtime暴露給我們的檔案:

iOS開發之runtime(一):runtime除錯環境搭建

雖然暴露給我們的不多,但其實已經能提供給我們很多功能,剛剛我們的物件建立就是一個典型的功能。 眾所周知,NSObject物件是Objective-C語言中幾乎所有物件的根類。換言之,任何一個物件的建立都是通過runtime實現的,僅此一點,runtime的重要性可見一斑,現在的iOS面試也越來越通過對runtime的面試來區分iOS開發人員的水平高低。

筆者研究runtime原始碼有一段時間了,隨著研究的深入,對runtime的實現也越來越感興趣,因此想寫一套系列教程來和大家討論runtime的底層實現。


本文完整版詳見筆者小專欄:xiaozhuanlan.com/runtime


下載原始碼

蘋果開源了runtime的實現,在網站 opensource.apple.com/source/objc… 中可以找到各個版本的runtime原始碼。 但提供的是一個個檔案,不方便打包下載,網站 opensource.apple.com/tarballs/ob…中提供了壓縮包的下載。

編譯

下載下來的runtime原始碼是執行不了的,缺少一些依賴檔案,找起來也比較繁瑣。這裡筆者fork了一份,供大家參考(該專案編譯過程大家可以參考這篇文章:objc - 編譯Runtime原始碼objc4-680):

runtime原始碼706

iOS開發之runtime(一):runtime除錯環境搭建

如圖,開啟工程後選擇工程debug-objc,點選run即可。由於debug-objc依賴於objc(即runtime的原始碼編譯的庫),因此我們在main函式中所有Objective-C的程式碼會呼叫我們編譯的runtime,從而方便我們除錯。

目錄分析

runtime原始碼目錄結構如下:

iOS開發之runtime(一):runtime除錯環境搭建

  • include 資料夾是我們引入的專案需要的依賴檔案

  • Public Headers 資料夾是對外暴露的,點開後我們不難發現,和文章開頭給出的檔案列表一模一樣:

    iOS開發之runtime(一):runtime除錯環境搭建

  • Private Headers 從字面意思瞭解,是私有的一些方法

  • Project Headers runtime專案中會用到的標頭檔案

  • Obsolete Headers 一些孤立的檔案,大部分可刪,只有hashtable2.h的檔案會被其他檔案使用到。

  • Obsolete Source 無實質用處,可全刪

  • Source目錄,是runtime的實現檔案集合,後面的文章主要是研究這個目錄。

小試牛刀

在我們的main.m中,輸入以下程式碼:

#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSObject *obj = [[NSObject alloc] init];
    }
    return 0;
}
複製程式碼

打斷點後,我們會發現NSObject *obj = [[NSObject alloc] init];方法最終會呼叫到runtime中的NSObject.mm中。也就是說,物件的建立都是在NSObject.mm中完成的。 具體實現流程,會在後面的文章中逐步揭曉。

注意

有人反饋專案編譯不能通過,報如下錯誤:

dyld: Symbol not found: _objc_debug_taggedpointer_obfuscator
Referenced from: /usr/lib/system/libxpc.dylib
Expected in: ~/Library/Developer/Xcode/DerivedData/objc-ehlaekvxhzkjtdcmtvyuyxuygmfk/Build/Products/Debug/libobjc.A.dylib
in /usr/lib/system/libxpc.dylib
複製程式碼

原因是因為系統版本太高,與runtime版本不相容導致的。目前最新的runtime可以在這裡下載: objc4-750適用於系統macOS Mojave。

點選桌面左上角可以看到系統版本

參考

dyld: Symbol not found: _objc_debug_taggedpointer_obfuscator

相關文章