天天看點

Objective-C runtime之運作時的基本特點(一)

原帖位址:http://blog.csdn.net/wzzvictory/article/details/8615569

作為一門動态程式設計語言,Objective-C 會盡可能的将編譯和連結時要做的事情推遲到運作時。隻要有可能,Objective-C 總是使用動态 的方式來解決問題。這意味着 Objective-C 語言不僅需要一個編譯環境,同時也需要一個運作時系統來執行編譯好的代碼。運作時系統(runtime)扮演的角色類似于 Objective-C 語言的作業系統,Objective-C 基于該系統來工作。是以,runtime好比Objective-C的靈魂,很多東西都是在這個基礎上出現的。是以它是值的你花功夫去了解的。

我們将從以下幾個方面了解Objective-C的運作時:

一、與靜态語言編譯後的差別

1、靜态語言

一個靜态語言程式,如下所示的C程式:

[cpp]  view plain copy

  1. #include < stdio.h >  
  2. int main(int argc, const char **argv[])  
  3. {  
  4.         printf("Hello World!");  
  5.         return 0;  
  6. }   

會經過編譯器的文法分析,優化然後将你最佳化的代碼翻譯成彙編語言,然後完全按照你設計的邏輯和你的代碼自上而下的執行。

2、Objective-C

很常見的一個消息發送語句:

[cpp]  view plain copy

  1. [receiver message]  

會被編譯器轉化成

[cpp]  view plain copy

  1. objc_msgSend(receiver, selector)  

如果有參數則為

[cpp]  view plain copy

  1. objc_msgSend(receiver, selector, arg1, arg2, …)  

消息隻有到運作時才會和函數實作綁定起來,而不是按照編譯好的邏輯一成不變的執行。 按照我的了解,編譯階段隻是确定了要去向receiver對象發送message消息,但是卻沒有發送,真正發送是等到運作的時候進行。是以,編譯階段完全不知道message方法的具體實作,甚至,該方法到底有沒有被實作也不知道。 這就有可能導緻運作時崩潰問題。

二、Objective-c runtime的幾點說明

1、runtime是開源的

是的,你沒看錯,runtime确實是開源的。目前蘋果公司和GNU各自維護一個開源的runtime版本,這兩個版本之間都在努力的保持一緻。其中蘋果的版本可以猛擊該連結下載下傳objc4-437.1.tar.gz

2、runtime是由C語言實作的

runtime做為Objective-C最核心的部分,幾乎全部由C語言實作。這裡的“幾乎”所指的例外就包含有的方法(比如下面要說道的objc_msgSend方法)甚至是用彙編實作的!!

3、runtime的兩個版本

Objective-C運作時系統有兩個已知版本:早期版本(Legacy)和現行版本(Modern)。

在現行版本中,最顯著的新特性就是執行個體變量是"健壯“(non-fragile)的:

 在早期版本中,如果您改變類中執行個體變量的布局,您必須重新編譯該類的所有子類。

 在現行版本中,如果您改變類中執行個體變量的布局,您無需重新編譯該類的任何子類。

此外,現行版本支援聲明property的synthesis屬性器。

目前iPhone 程式和 Mac OS X v10.5 及以後的系統中的 64 位程式使用的都是 Objective-C 運作時系統的現行版 本。其它情況(Mac OS X 系統中的 32 位程式)使用的是早期版本。

三、和runtime system互動的三種方式

1、通過Objective-C源代碼

大部分情況下,運作時系統在背景自動運作,我們隻需編寫和編譯 Objective-C 源代碼。

當編譯Objective-C類和方法時,編譯器為實作語言動态特性将自動建立一些資料結構和函數。這些資料 結構包含類定義和協定類定義中的資訊,如在Objective-C 2.0 程式設計語言中定義類和協定類一節所讨論 的類的對象和協定類的對象,方法選标,執行個體變量模闆,以及其它來自于源代碼的資訊。運作時系統的主要功能就是根據源代碼中的表達式發送消息。

2、通過類NSObject的方法

Cocoa程式中絕大部分類都是NSObject類的子類,是以大部分都繼承了NSObject類的方法,因而繼承 了NSObject的行為(NSProxy類是個例外)。然而,某些情況下, NSObject類僅僅定義了完成某件事情的模闆,而沒有提供所有需要的代碼。

例如,NSObject 類定義了description方法,傳回該類内容的字元串表示。這主要是用來調試程式 ——GDB 中的 print-object 方法就是直接列印出該方法傳回的字元串。NSObject 類中該方法的 實作并不知道子類中的内容,是以它隻是傳回類的名字和對象的位址。NSObject 的子類可以重新實作該方法以提供更多的資訊。例如,NSArray 類改寫了該方法來傳回 NSArray 類包含的每個對象的内容。

某些 NSObject 的方法隻是簡單地從運作時系統中獲得資訊,進而允許對象進行一定程度的自我檢查。 

例如,class 傳回對象的類;isKindOfClass:和 isMemberOfClass:則檢查對象是否在指定的 類繼承體系中;respondsToSelector:檢查對象能否響應指定的消息;conformsToProtocol: 檢查對象是否實作了指定協定類的方法;methodForSelector:則傳回指定方法實作的位址。

3、通過運作時系統的函數

運作時系統是一個有公開接口的動态庫,由一些資料結構和函數的集合組成,這些資料結構和函數的聲明 頭檔案在/usr/include/objc中。這些函數支援用純C的函數來實作和Objective-C同樣的功能。還有一些函數構成了 NSObject 類方法的基礎。這些函數使得通路運作時系統接口和提供開發工具成為可 能。盡管大部分情況下它們在 Objective-C 程式不是必須的,但是有時候對于 Objecitve-C 程式來說某些函 數是非常有用的。 這些函數的文檔參見 Objective-C 2.0 運作時系統參考庫。

-------------未完待續-------------

繼續閱讀