iOS 大師養成之路--對象的本質

1、對象究竟是什麼?

咱們的Xcode其實很強大,集成了不少牛逼的工具,clang就是其中之一,咱們可使用如下的命令對.m文件進行編譯咱們就能夠看到咱們的OC 編譯到底層的C或者C++究竟是怎麼樣的c++

我這裏的例子是使用的是main.m 文件,各位能夠根據具體SDK的文件路徑和須要編譯的文件去編譯研究
clang -x objective-c -rewrite-objc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk main.m  //模擬器的使用命令
clang -x objective-c -rewrite-objc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk  main.m //真機的使用命令
複製代碼

咱們編譯完看到的就是一個C++的結構體,沒錯就是一個objec_class的結構體,他的結構體長成這個樣子: objective-c

固然下面還有不少的函數,太長了,不浪費地方了。咱們發現有些有意思的問題:

  • isa 爲何沒有? --> 在父類的結構體裏面,直接繼承
  • 它仍是繼承之objc_object? -->

  • 個人對象呢爲何只有一個isa 指針?--> 其實這裏我只能這麼解釋下,可能不是很專業可是意思能表達清楚。在編譯階段,全部的類都有本身的內存空間了,至關於已經建好統一的毛坯了,只是要如何裝修每一個對象有每一個對象的想法。這樣一來對象實例化話時就很快了只要按照本身的想法直接裝修好就行,再貼上本身的名字標示全部權。

2、神祕的isa

在上面我有說到對象在實例化時返回的就是一個isa,並且就幹了一件事情,就是把咱們實例化出來的對象跟類進行綁定。那麼isa就是是個啥玩意?且看如下分解:數組

union isa_t {
    isa_t() { }
    isa_t(uintptr_t value) : bits(value) { }

    Class cls;//類對象
    uintptr_t bits;//位域
#if defined(ISA_BITFIELD)
    struct {
        ISA_BITFIELD;  // defined in isa.h
    };
#endif
};
複製代碼
  • 咱們看到其實就是一個聯合體,就多是bits 也多是cls.-->這也進一步說明對象的本質。
  • 那麼要是bits還能怎麼綁定類呢?咱們再看看bits都有啥
# define ISA_BITFIELD \
      uintptr_t nonpointer        : 1;                                       \表示是否對 isa 指針開啓指針優化
      uintptr_t has_assoc         : 1;                                       \是否有關聯對象
      uintptr_t has_cxx_dtor      : 1;                                       \否有 C++ 或者 Objc 的析構器
      uintptr_t shiftcls          : 33; /*MACH_VM_MAX_ADDRESS 0x1000000000*/ \存儲類指針的值
      uintptr_t magic             : 6;                                       \用於調試器判斷當前對象是真的對象仍是沒有初始化的空間
      uintptr_t weakly_referenced : 1;                                       \是否被指向或者曾經指向一個 ARC 的弱變量
      uintptr_t deallocating      : 1;                                       \是否正在釋放
      uintptr_t has_sidetable_rc  : 1;                                       \當對象引用技術大於 10 時,則須要借用該變量存儲進位
      uintptr_t extra_rc          : 19\當表示該對象的引用計數值,其實是引用計數值減 1,當大於10時須要借用上面的標誌位
複製代碼

這是一個宏定義的位域,後面的數字表示佔有的位數。其實就是對isa進行了優化,把一個8字節的空間進行了高效使用,從而存儲了更多的東西,如剛剛的cls 就存儲在shiftcls中。緩存

isa走位

相信有不少人已經有所瞭解,可是說到isa,我仍是介紹下走位bash

  • 實例化對象的isa -> 類, 類的isa -> 元類,元類的isa -> 根元類,根元類的isa -> 根元類本身。流程大概就是如此,若是是NSObject的實例化對象會少一次。
  • 附上isa走位圖
  • isa走位圖解讀,虛線表示的是isa走位,實線表示的是superclass的繼承關係。rootClass是NSObject,萬物皆對象

3、cache是什麼?

字面意思就是緩存,事實上Runtime進行消息查找的時候若是每次查完就直接扔了很浪費,哪些常常用的或者最近查找過的方法會進行緩存,這樣就提升了方法調用的效率。具體介紹能夠參考我以前寫過的關於cache_t的分析的文章 https://juejin.im/post/5e1469f6e51d4541657776b4app

4、bits 是什麼?

不知道咱們是否是很好奇,既然對象實例化以後啥都沒有那麼我寫的那些屬性、方法都在哪呢?難道在類裏面嗎? 還真是,不過這個類是相對的,類是對象的類,元類是類的類,以此類推。bits裏面就存了對象的屬性、實例化方法(注意是實例化方法,類方法在元類的bits裏面ide

一、bits 結構體

咱們看到了bits.data()返回的是一個class_rw_t *結構體指針,說明了這個bits裏面存的就是這個結構體數據。函數

  • rw意味着什麼,可讀可寫區域?誰寫?確定不是咱們普通iOS開發人員寫進去的,是編譯器在編譯、運行階段對代碼中的類、對象的解析翻譯,把方法、屬性、協議寫入到這麼一個可讀可寫的區域。
  • 所有都寫在這裏嗎?不是。class_ro_t,read only還有一個只讀區域
  • 那rw裏寫的是啥?類別、類拓展中的方法、屬性、協議。
uint32_t flags;
    uint32_t version;

    const class_ro_t *ro;

    method_array_t methods;
    property_array_t properties;
    protocol_array_t protocols;

    Class firstSubclass;
    Class nextSiblingClass;

    char *demangledName;
複製代碼
  • class_ro_t 結構體介紹,從下面的結構體咱們能夠看到有方法數組、協議數組、屬性數組,可是還有個ivars,咱們給類添加屬性時,系統會默認實現set、get方法,同時還生成一個對應的成員變量。這個成員變量就存在ivars裏。
struct class_ro_t {
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;
#ifdef __LP64__
    uint32_t reserved;
#endif

    const uint8_t * ivarLayout;
    
    const char * name;
    method_list_t * baseMethodList;
    protocol_list_t * baseProtocols;
    const ivar_list_t * ivars;

    const uint8_t * weakIvarLayout;
    property_list_t *baseProperties;

    method_list_t *baseMethods() const {
        return baseMethodList;
    }
};
複製代碼

二、實際看看驗證下

咱們來先自定義一個類,配置好objc的源碼,用LLDB調試看看內存中的數據工具

  • 準備好一個自定義的類,在main函數中直接調用

  • 獲取bits中的數據 post

  • ro中的數據

  • 讀屬性,nickName 已經在數組中的第一個,總數也是一個(咱們的類中也只寫了一個)。

  • 讀方法,屬性對應的set、get方法,咱們本身定義的一個實例化方以及一個c++的函數

  • 讀成員變量,hobby以及屬性自動生成的_nickName都在這裏了

5、寫在最後的感想

在這些底層的研究過程當中,思考蘋果開發工程師的開發思路和設計思想是一件很享受的事情,弄清楚他們怎樣作到讓這個代碼的效率如此之高對本身的開發水平提升有很好地幫助,用C++ 寫過遊戲的朋友估計體驗比較深入,遊戲全部的都是本身實現,除了場景以及渲染用到的遊戲引擎。

有興趣一塊兒交流的朋友,能夠加 QQ:578200388

相關文章
相關標籤/搜索