iOS Objective -C Runtime 運行時之一: 類與對象

來源:互聯網
上載者:User

標籤:

 // ---------------------------------------------------

參考:南峰子的技術部落格 http://southpeak.github.io

//----------------------------------------------------

     OC語言是一門動態語言,它將很多靜態語言在編譯和連結時期做的事放到了運行時來處理。這種動態語言的優勢在於:我們編寫代碼時更具靈活性,如我們可以把訊息轉寄給我們想要的對象,或者隨意交換一個方法的實現等。

     這種特性意味著OC不僅需要一個編譯器,還需要一個運行時系統來執行編譯的代碼,對於OC來說,這個運行時系統就像一個作業系統一樣,它讓所有的工作可以正常的運行。這個運行時系統即Objc Runtime。 Objc Runtime其實是一個Runtime庫,它基本上是用C喝彙編寫的,這個庫使得C語言有了物件導向的能力

    Runtime庫主要做下面幾件事:

    1.封裝:在這個庫中,對象可以用C語言中的結構體表示,而方法可以用C函數來實現,另外再加上了一些額外的特性。這些結構體和函數被runtime函數封裝後,我們就可以在程式運行時建立、檢查、修改類、對象和它們的方法了。

    2.找出方法的最終執行代碼:當程式執行[object doSomething]時,會向訊息接收者(object)發送一條訊息(doSomething),runtime會根據訊息接收者是否能響應該訊息而做出不同的反應。這將在後面詳細介紹。

    OC runtime目前有兩個版本:Modern runtime和Legacy runtime。Modern Runtime覆蓋了64位的Mac OS X Apps,還有iOS Apps,Legacy Runtime 是早起用來給32位Mac OS X Apps用的。

 

runtime的基本工作原理,以及如何利用它讓程式編的更加靈活。

類與對象基礎資料結構

Class

OC中,類是由Class 類型來表示的,它實際上是一個指向objc_class結構體的指標。定義如下:

typedef struct objc_claa *Class ;

查看objc/runtime.h中objc_class結構體的定義如下:

struct objc_class {
    Class isa OBJC_ISA_AVAILABILITY;

#if !__OBJC2__

     Class super_class                           OBJC2_UNAVAILABLE; // 父類

     const char *name                          OBJC2_UNAVAILABLE; // 類名

     long version                OBJC2_UNAVAILABLE; // 類的版本資訊,預設為0

     long info                 OBJC2_UNAVAILABLE; // 類資訊,供運行期使用的一些位標識

     long instance_size             OBJC2_UNAVAILABLE; // 該類的執行個體變數大小

     struct objc_ivar_list *ivars        OBJC2_UNAVAILABLE; // 該類的成員變數鏈表

     struct objc_method_list  **methodLists   OBJC2_UNAVAILABLE; // 方法定義鏈表 

     struct objc_cache *cache        OBJC2_UNAVAILABLE;  // 方法緩衝

     struct objc_protocol_list *protocols   OBJC2_UNAVAILABLE;  // 協議鏈表

#endif 

}OBJC2_UNAVAILABLE;

在這個定義中,下面幾個欄位是我們感興趣的

1.isa: 需要注意的是,在OC中,所有的類自身也是一個對象,這個對象的Class裡面也有一個isa指標,它指向metaClass(元類),後面詳解

2.super class: 指向該類的父類,如果該類已經是最頂層的根類(如NSObject或NSProxy),則super_class為NULL.

3.cache: 用於緩衝最近使用的方法. 一個接收者對象收到一個訊息時,它會根據isa指標去尋找能夠響應這個訊息的對象,在實際使用中,這個對象只有一部分方法是常用的,很多方法其實很少用或者根本用不上,這種情況下,如果每次訊息來,我們都到methodLists中遍曆一遍,效能勢必很差,這時,cache就派上用場了,在我們每次調用過一個方法後,這個方法就會被緩衝到cache列表中,下次調用的時候,runtime會優先去cache中尋找,如果cache沒有,採取methodLists中尋找方法.這樣,對於那些經常用到的方法的調用,便提高了調用的效率

4.version: 我們可以使用這個欄位來提供類的版本資訊,這對於類的序列化非常有用,它可以讓我們識別出不同類定義版本中執行個體變數布局的改變,針對cache,下面例子來說明執行過程"

NSArray *array = [[NSArray alloc] init];

流程 : 

       1.[NSArray alloc]執行, 因為NSArray 沒有+alloc方法,於是去父類NSObject尋找

    2.檢測NSObject是否響應 + alloc方法,發現響應, 於是檢測NSArray類,並根據其所需的記憶體空間開始分配記憶體,然後把isa指標指向NSArray類.同時,+alloc也被加進cache列表裡

    3.接著,執行-init方法,如果NSArray回應程式法,則直接將其加入cache;如果不響應,則取父類尋找.

    4.在後期的操作中,如果再以[[NSArray alloc] init] 方式建立數組,則會直接從cache中取出相應的方法,直接調用

 

objc_object與id

objc_object是表示一個類的執行個體結構體,它的定義如下(objc/objc.h)

struct objc_object {

 Class isa OBJC_ISA_AVAILABILITY;

};

typedef struct objc_objct *id;

可以看到,這個結構體只有一個字,即指向其類的isa指標,這樣,當我們向一個OC對象發送訊息時,執行階段程式庫會根據執行個體對象的isa指標找到這個執行個體對象所屬的類.Runtime庫會在類的方法列表及父類的方法列表中尋找與訊息對應的selector指向的方法.找到後即運行這個方法.

   當建立一個特定類的執行個體對象時,分配的記憶體包含一個objc_object資料結構,然後是累的額執行個體變數的資料.NSObject類的alloc和allocWithZone:方法使用函數class_createInstance來建立objc_object資料結構.

   另外還有我們常見的id,它是一個objc_object結構類型的指標.它的存在可以讓我們實作類別似於C++眾泛型的一些操作,該類型的對象可以轉換為任何一種對象,有點類似於C語言中void*指標類型的作用.

iOS Objective -C Runtime 運行時之一: 類與對象

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.