深入研究Runtime(1) - 前言
首先我們先看看文檔如何描述Runtime的,如下:
The Objective-C language defers as many decisions as it can from compile time and link time to runtime. Whenever possible, it does things dynamically. This means that the language requires not just a compiler, but also a runtime system to execute the compiled code. The runtime system acts as a kind of operating system for the Objective-C language; it’s what makes the language work.
大概的意思就是:OC語言盡可能的動態地
處理事情,將決定盡可能地從編譯時
和鏈接時
推遲到運行時
。意味著,OC語言不僅僅需要一個編譯器,還需要一個運行時系統
執行已經編譯好的代碼。
下面將從兩個方面學習Runtime:
- OC 運行時系統是如何工作的?
- 如何使用運行時系統?
補充:
其實發展到現在,Runtime技術已經發展了兩個版本,一個OC2.0以后的modern
版本,和之前legacy
版本。
這兩個版本的主要區別是:
- 類中實例變量的排序改變后,是否需要重新編譯該類的子類,在
legacy
版本是必須的,而modern
則不必須。 modern
版本支持@property屬性
支持的平臺:
modern
:iPhone系統 && 64-bit OS X v10.5后的系統
legacy
:32bit OS X 系統
與運行時系統交互的的方式( 詳細的交互在后面章節再說明 )
分為三個不同的層次:
- Objective-C 源碼
- NSObject 的方法
- 直接調用 runtime 函數
Objective-C 源碼
當編譯器編譯OC的類和方法時,會生成數據結構
和函數調用
實現語言的動態特性。
-
數據結構
在哪里獲取到信息?- 類和分類定義 / 協議聲明
- 類對象和協議對象
- 方法選擇器( method selector )
- 實例變量模板
- 源碼提取到的其它信息
-
函數調用
:- 最主要的運行時函數就是發送消息,由源碼的消息表達式調用。例如:[dog run]這個表達式會調用運行時的
發送消息函數
- 最主要的運行時函數就是發送消息,由源碼的消息表達式調用。例如:[dog run]這個表達式會調用運行時的
NSObject 的方法
其中一些方法可以簡單查詢運行時系統獲取信息。這些方法可以讓對象實現自省
+(Class)class // 獲得類對象
-(BOOL)isKindOfClass:(Class)aClass // 是否是指定類或者其子類
-(BOOL)isMemberOfClass:(Class)aClass // 是否是指定類
-(BOOL)respondsToSelector:(SEL)aSelector // 是否實現指定方法或者其父類實現
+(BOOL)conformsToProtocol:(Protocol *)aProtocol // 類是否實現了指定協議
-(IMP)methodForSelector:(SEL)aSelector // 定位和返回接收者方法實現的地址,所以可以像函數調用一樣
Cocoa中大多數的類都繼承于NSObject( 特例:NSProxy ),所以大多數類都擁有上述自省
方法。在NSObject中,大多數方法只是簡單地實現,例如:
+(NSString *)description // 默認返回類名和地址
詳細實現功能還需自己重寫。
直接調用 runtime 函數
運行時系統是一個動態共享庫
,/usr/include/objc 目錄下提供了一套函數
和數據結構
的公共接口。
補充:
-
什么是selector?
一個對象選擇一個方法執行的名稱
,又或者是源碼編譯后,取代這個名稱
的唯一標識
。 -
selector的作用:
在OC源碼階段
,selector一般當前是方法的唯一標識。而在運行時
,selector就作為一個動態函數指針
,根據給的方法名指向相對應類中的方法的具體實現
。 -
獲得一個selector:
編譯好的類型是:SEL
,有兩種途徑可以獲得編譯時
,使用@selector
指令:SEL aSelector = @selector(methodName);
運行時
,使用NSSelectorFromString
函數SEL aSelector = NSSelectorFromString(@"methodName");
-
調用selector:
使用performSelector:方法SEL aSelector = @selector(run); // 運行時會自動指向 對應類 的方法實現
[aDog performSelector:aSelector];
[anAthlete performSelector:aSelector];
為了防止篇章過長,后面內容分篇章記錄
文/老譚是誰(簡書作者)
來自:http://www.jianshu.com/p/2cb150a6caba