日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

详解Objective-C消息传递机制

發布時間:2023/12/20 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 详解Objective-C消息传递机制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

 Objective-C獲取消息工作機制是本文要介紹的內容,看name?mangling的時候,也講到了Objective-C的name mangling,于是又重新讀了一下Objective-C?2.0?programming Language以及Objective-C 2.0?Runtime?Reference里的相關內容,自己歸納一下??。

 

???MyClass.h ?
???@interface?MyClass?:?NSObject ?
???{ ?
????} ?
???@end ?
???MyClass.m ?
???#import?< span>usr/include/objc/runtime.h>?
???#import?“MyClass.h” ?
???void?myClassIMP(id?_rec,?SEL?_cmd,?int?theInt) ?
???{ ?
??????NSLog(@”dynamic?added?method:%d”,theInt); ?
???} ?
? ?
-?(id)init ?
{ ?
????if(?(?self?=?[super?init])?!=?nil?) ?
????{ ?
???class_addMethod([MyClass?class],?@selector(dynGeneratedMethod:),(IMP)myClassIMP,”v@:i”); ?
?????} ?
????return?self; ?
} ?
?
Main.c ?
#import?“MyClass.h” ?
int?main(int?argc,?char?*argv[]) ?
{ ?
??MyClass?theInstance?=?[[MyClass?alloc]?init]; ?
??[theInstance?dynGeneratedMethod:10]; ?
?return?0; ?
}?

  這段代碼執行的結果是在控制臺上輸出:


dynamic?added?method:10?

  接著來詳細分析一下上面的代碼:

  在ObjC的類中這樣的一個聲明?– (void)foo:(int)a;被稱作方法(method),而在調用的地方: [theClass foo:10];則被稱之為發送消息(send message),具體來說是給對象theClass 發送foo:消息,注意這里foo后面的”:”,它也是消息名稱的一部分,最前面的-代表實例方法,+代表類方法??。而類似的語句,在C或C++中,通常被稱為呼叫函數(call function),在ObjC中,函數(function)一詞很少用到,不是它不存在,而是它被ObjC runtime給隱藏了起來??。
???
如前所述,ObjC是以消息機制來工作的,但其實諸如-(void)foo:(int)a的語句在編譯時被objc_msgSend(receiver,selector,arg1,arg2,….)替換了,所以其實每一條發送消息的代碼本質上還是調用函數(call function),不過他們調用的都是同一個函數objc_msgSend(也可能是objc_msgSend_stret(返回值是結構體),objc_msgSend_fpret(返回值是浮點型)等)

  分析objc_msgSend的參數,第一個receiver的類型是id,代表接受消息的對象,第二個是selector代表接收對象的方法,后面的是該方法的參數,之前那條語句的被編譯器替換后就是:


[theClass?foo:10]??->?objc_msg(theClass,@selector(foo:),10);?

  因為消息的接受對象和接受對象的方法都參數化,所以在運行時刻,接受對象和接受對象的方法都可以是動態的!

  比如說程序里面可以這樣寫:


id?helper?=?getTheReceiver(); ?
SEL?request?=?getTheSelector(); ?
[helper?performSelector:request];?

  它的實現是基于ObjC runtime.?NSObject類實現了這套機制,所以每一個繼承于NSObject的類都能自動獲得runtime的支持??。在這樣的一個類中,有一個isa指針,指向該類定義數據結構體,這個結構體是由編譯器編譯時為類(須繼承于NSObject)創建的.在這個結構體中有包括了指向其父類類定義的指針以及Dispatch table. Dispatch table是一張SEL和IMP的對應表??。

  對于名稱相同的方法,他們都有相同的SEL,方法的名稱不包括類名稱,所以子類和父類中的同名方法擁有相同的SEL,但是他們的實現可以各不相同,因而在他們各自的Dispatch表中SEL所對應的IMP是不同的,IMP是一個函數指針,而雖然每一個SEL對應的是一個方法的名稱,但考慮到效率,SEL本身是一個整型,編譯器會另外生成一張SEL和方法名稱對應的表??。有了這樣的結構,objc就可以實現多態了??。還是這行代碼:


[theClass?foo:10];?

  是向theClass發送了foo:消息,那么首先在theClass的類結構的Dispatch table里找有沒有對應的SEL,如果有的話,就表示theClass有響應該消息的方法,程序就跳到該方法的代碼地址頭(由IMP指定),開始執行??。如果在theClass的Dispatch table找不到對應的SEL,那么就會通過isa所指的結構體中包含的父類指針,到父類里面去尋找,如果到最后還是沒有找到,就會出現runtime error.所以說,即使theClass以及它的父類都沒有定義-(void) foo:(int)a方法,程序還是可以通過編譯,但如果是用xcode的話,編譯器會有警告,告知theClass可能無法響應該消息??。不會報錯的原因是類的方法也可以在執行時刻創建!上面的代碼:


class_addMethod([MyClass?class],?@selector(dynGeneratedMethod:),(IMP)myClassIMP,”v@:i”);?

  就是給MyClass類在執行時刻增加了一個響應dynGeneratedMethod:消息的方法,這樣之后對任何MyClass的instance類發送dynGeneratedMethod:消息,就會得到響應了.myClassIMP是類收到該消息時要調用的方法,其聲明如下:


void?myClassIMP(id?_rec,?SEL?_cmd,?int?theInt)?

  這個方法的前面兩個參數是必須的,之后的參數才是我們實際用到的參數,數目和@selector()中的冒號數一樣,冒號數代表的就是參數個數??。第一個參數是消息的接受對象,是MyClass的實例,第二個參數是由SEL代表的具體消息??。

  Class_addMethod的最后一個參數是表示dynGeneratedMethod:的返回值和參數信息,不過我自己試了一下,這個參數不起作用??。

  幾個要點:

  1、對于C中被稱為函數(function)和函數調用(function call)的地方,在ObjC中被叫做方法(method)和發送消息(send message).試圖調用未定義的方法會導致編譯錯誤,而發送一條消息,即使沒有任何類定義了響應該消息的方法,編譯時也不會報錯,從語義上講這也是對的,發一條消息本來就不要求一定有人會響應,不過如果執行到發送消息的代碼時真的沒有類可以響應的話,是會發生runtime error,為了避免這種事情發生,可以先進行檢測,這樣寫:


if(?[myClass?respondsToSelector:@selector(foo:)]) ?
{ ?
???[myClass?foo:10]; ?
}?

  我感覺ObjC這樣的一套sender receiver的定義更注重面向對象的概念??。類是一個接收者(receiver),如果定義了某個方法,就可以接收和這個方法名稱相同的消息??。而使用該類的client(sender),則嘗試向該類發送消息.如果匹配了,就跳到類的方法里執行??。

  2、方法名稱是諸如foo:,不包括返回類型,參數類型,而又因為一個foo:對應于一個SEL,所以說ObjC不支持相同的foo:有不同的返回類型,也不支持重載??。不過類方法和實例方法可以有相同的名字,而又有不同類型的參數和返回類型,因為它們不是處在同一張dispatch table中??。

  3、不僅類的方法可以運行時刻創建,類本身也可以在運行時刻創建,前面提到繼承于NSObject的類,編譯器會幫忙生成ObjC runtime所需要的類結構定義,只要我們在代碼里也按照那個結構創建了自己的類,那一樣可以獲得ObjC runtime的支持??。?

?

轉載于:https://www.cnblogs.com/DamonTang/archive/2012/11/08/2760580.html

總結

以上是生活随笔為你收集整理的详解Objective-C消息传递机制的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。