1. 程式人生 > >Objective-C runtime之執行時的基本特點(三)

Objective-C runtime之執行時的基本特點(三)

學了那麼久的Objective-C,給我的感覺就是它什麼都是動態的,你將會聽到一個新的名詞:

一、動態方法解析

1、+(BOOL) resolveInstanceMethod:(SEL) sel

這是NSObject根類提供的類方法,呼叫時機為當被呼叫的方法實現部分沒有找到,而訊息轉發機制啟動之前的這個中間時刻。

2、@dynamic關鍵字

Objective-C2.0 提供了@dynamic關鍵字,從名字上可以看出來,它一定是跟動態相關的。猜對了,這個關鍵字告訴編譯器,某個屬性的實現是動態的。如果我們在@interface介面檔案中聲明瞭一個屬性,如下所示:

  1. @property(nonatomic,retain) NSString    *name;  
在@implementation檔案中做了如下宣告:
  1. @dynamic name;  
就表示編譯器須動態地生成該屬性對應的方法。如果想將該屬性的-(void)setName:(NSString *)name方法用dynamicMethodIMP函式來代替,可以這樣做:
  1. void dynamicMethodIMP(id self, SEL _cmd)  
  2. {  
  3.     // implementation ....  
  4. }  
  5. + (BOOL)resolveInstanceMethod:(SEL)sel  
  6. {  
  7.     NSLog(@"sel is %@", NSStringFromSelector(sel));  
  8.     if(sel == @selector(setName:)){  
  9.         class_addMethod([self class],sel,(IMP)dynamicMethodIMP,"[email protected]:");  
  10.         return YES;  
  11.     }  
  12.     return [super resolveInstanceMethod:sel];  
  13. }  
在resolveInstanceMethod的實現中,我們通過class_addMethod方法動態的向當前物件增加了dynamicMethodIMP函式,來代替-(void)setName:(NSString *)name的實現部分,從而達到了動態生成name屬性方法的目的。

值得說明的是:

①在我看來,@dynamic關鍵字的作用並非想象中的那麼大,理由是,如果沒有在@implementation檔案中做出@dynamic宣告,而在resolveInstanceMethod方法中做了方法重定向的工作,一樣能順利的呼叫dynamicMethodIMP函式。唯一的不同之處在於進行了@dynamic宣告時,編譯器不會告警而已!!

②在上個例子中,我們自己實現了-(void)setName:(NSString *)name方法,則在執行的時候,呼叫完我們實現的-(void)setName:(NSString *)name方法後,執行時系統仍然會調+(BOOL) resolveInstanceMethod:(SEL) sel方法,只不過這裡的sel會變成_doZombieMe,從而我們實現重定向的if分支就進不去了。

③"[email protected]:"屬於Objective-C型別編碼的內容,感興趣的同學可以自己google一下。

二、runtime system訊息轉發機制

物件是謙恭的,它會接收所有傳送過來的訊息,哪怕這些訊息自己無法響應。問題來了:當物件無法響應這些訊息時怎麼辦?runtime提供了訊息轉發機制來處理該問題。

當外部呼叫的某個方法物件沒有實現,而且resolveInstanceMethod方法中也沒有做重定向處理時,就會觸發- (void)forwardInvocation:(NSInvocation *)anInvocation方法。在該方法中,可以實現對不能處理的訊息做的一些預設處理,也可以以其它的某種方式來避免錯誤被丟擲。像forwardInvocation:的名字一樣,這個方法通常用來將不能處理的訊息轉發給其它的物件。通常我們重寫該方法的方式如下所示:

  1. -(void)forwardInvocation:(NSInvocation *)invocation  
  2. {  
  3.     SEL invSEL = invocation.selector;  
  4.     if ([someOtherObject respondsToSelector:invSEL])  
  5.         [anInvocation invokeWithTarget:someOtherObject];  
  6.     } else {  
  7.         [self doesNotRecognizeSelector:invSEL];   
  8.     }                                                                            
  9. }  

怎麼看著有點像多繼承呀???你說對了,訊息轉發提供了多重繼承的很多特性。然而,兩者有很大的不同:多重繼承是將不同的行為封裝到單個的物件中,有可能導致龐大的,複雜的物件。而訊息轉發是將問題分解到更小的物件中,但是又以一種對訊息傳送物件來說完全透明的方式將這些物件聯絡起來。總之,Objective-C通過這種方式,一定程度上減小了自己不支援多繼承的劣勢。

相關推薦

Objective-C runtime執行基本特點

學了那麼久的Objective-C,給我的感覺就是它什麼都是動態的,你將會聽到一個新的名詞: 一、動態方法解析 1、+(BOOL) resolveInstanceMethod:(SEL) sel 這是NSObject根類提供的類方法,呼叫時機為當被呼叫的方法實現部分沒有找到,而訊息轉發機制啟動之前的這個

Java——多執行基本使用 餓漢式和懶漢式的單例設計模式,多執行緒之間的通訊

這一則部落格主要寫的是單例設計模式,與實現多執行緒之間的通訊等等~ 1.單例設計模式:保證類在記憶體中只有一個物件 2.保證類在記憶體中只有一個物件            &

百度地圖js 畫執行軌跡執行軌跡標註文字

在執行軌跡中需要在起止點加上資訊提示,實現方法如下: //加資訊提示的文字方法 setInfoBox:function (tracksPart,marker) { // var point = new BMap.Point(tracksPart.

Objective-C是動態執行語言的個人理解

      以前開發時沒有特別注意這些細節問題,今天突然被問到,一下子懵圈了,經過一番查詢和比較,再加上小編的理解終於是瞭解的差不多了,現在分享給大家! 1、什麼是動態語言? 動態語言,是指程式在執行

執行型別資訊RTTI遞迴列印類資訊

深度優先 public class ClassPrint { private static void printSupers(Class<?> clazz) { String name = clazz.getCanonicalName(); System.out.p

C++11 | 執行型別識別RTTI

type_info類 typeid操作符 type_index類 type_info type_info類在標頭檔案<typeinfo>中定義,代表了一個C++型別的相關資訊。一般由t

c#執行緒同步淺析1-----輕量級同步Interlocked

        在c#裡面,實現執行緒同步方法有很多種。我瞭解到的至少有8種。這裡先講下,一種比較簡單的同步方法-------輕量級同步Interlock。         為什麼說它是輕量級呢?因為它僅對整形資料(即int型別,long也行)進行同步。如果你學過作業系統裡面

vue學習路 - 4.基本操作

align 過去 開始 就會 binding 效果 不可 exp 功能 vue學習之路 - 4.基本操作(下) 簡述:本章節主要介紹 vue 的一些其他常用指令。 Vue 指令   這裏將 vue 的指令分為系統內部指令(vue 自帶指令)和用戶自定義指令兩種。 系統內部指

執行緒的基本操作

volatile關鍵字:   修飾變數,可以保證變數的可見性,但是無法保證對變數複合操作的原子性,如:        static volatile int = 0;        pub

JavaScript總結DOM基本操作

  DOM(Document Object Model),即文件物件模型。當我們建立了一個網頁並把它載入到Web瀏覽器上,DOM就在幕後悄然而生,因為它把你所編寫的網頁文件轉換為一個文件物件。   我們可以這麼理解DOM,把DOM看做一棵節點樹,主要由元素節點、屬性節點、文字節點三種節點構成。例如下方的一行

Java——多執行基本使用 執行緒組和執行緒池的使用,工廠設計模式的使用

1.執行緒組的概述和使用 Java中使用ThreadGroup來表示執行緒組,它可以對一批執行緒進行分類管理,Java允許程式直接對執行緒組進行控制。            &n

Java——多執行基本使用

在學習多執行緒時,如果聯絡作業系統來學習,會覺得很好理解。因為學習作業系統時候,有同步,互斥,鎖的一些概念~ 給個連結到上一篇~https://blog.csdn.net/zoweiccc/article/details/83002176 8.加入執行緒   &n

《自己動手寫java虛擬機器》學習筆記-----執行緒私有執行資料區go

     專案地址:https://github.com/gongxianshengjiadexiaohuihui      在執行java程式時,Java虛擬機器需要使用記憶體來存放各種各樣的資料,Java虛擬機器規範把這些記憶體的區

複習JavaScript基本語法——getElement[...]方法使用

JavaScript核心document.getElementById() document.getElementById()是根據id獲取標籤物件 //獲取標籤物件的值 //文字域和文字框都用value取值 document.getElementById("u

Java面向物件與多執行緒綜合實驗輸入輸出流

瞭解Java中I/O流的概念和種類;掌握位元組流處理和字元流處理,包括File類,InputStream/OutputStream及其子類,Reader/Writer及其子類;熟練掌握檔案的順序處理,隨機訪問處理;熟悉物件序列化的概念和方法。 編寫程式,實現檔案管理系統中的檔案上傳/下載模組

C++學習迴圈和關係表示式1

在c語言中我這部分還算學習的挺好,所以這部分我只新增一些我不太懂的點: 1.通常,cout在顯示bool值之前將它們轉換為int,但是在前面使用cout.setf(ios:boolalpha)函式呼叫設定了一個標記,該標記命令cout顯示true和false,而不是1和0;

C++ 學習筆記 變數和基本型別

C++ 學習筆記 一、變數和基本型別概述 型別是所有程式的基礎。型別告訴我們資料代表什麼意思以及可以對資料執行哪些操作。 c++基本型別: 字元型 整型 浮點型 c++ 還提供了可用於自定義資料型別的機制,標準庫正式利用了這些機制定義了許多更復雜的型別,比如可變長字串string 和vector等。此外,

【Visual C++】遊戲開發筆記十 基礎動畫顯示 透明動畫的實現

                作者:毛星雲    郵箱: [email protected]    歡迎郵件交流程式設計心得"透明動畫”是遊戲中一定會用到的基本技巧,它通過圖案的連續顯示及圖案本身背景的透明化處理,在背景圖上產生出栩栩如生的動畫效果。看過之前筆記的朋友們應該知道,在筆記六裡我們介紹

Android NDK——必知必會JNI的C++操作函式詳解和小結

引言 上一篇講解了一些關於JNI和NDK的必知必會的理論知識和機制,由於篇幅問題把關於JNI的重要的函式放到這篇,具體使用留到下一篇,此係列文章基連結: 一、JNI中的函式概述 在JNI層我們基本上都是通過env指標來呼叫jni.h標頭檔案裡定義的函式,JNI

【SSH進階路】Hibernate基本對映

【SSH進階之路】Hibernate基本原理(一) ,小編介紹了Hibernate的基本原理以及它的核心,採用物件化的思維操作關係型資料庫。 【SSH進階之路】Hibernate搭建開發環境+簡單例項