久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

IOS SEL (@selector) 原理及使用總結(jié)(二)

 沒原創(chuàng)_去搜索 2015-07-05
轉(zhuǎn)自: http://blog.csdn.net/fengsh998/article/details/8614486

SEL消息機(jī)制工作原理是什么 

引用下面文章:

我們?cè)谥坝刑岬?一個(gè)類就像一個(gè) C 結(jié)構(gòu).NSObject 聲明了一個(gè)成員變量: isa. 由于 NSObject 是所有類的根類,所以所有的對(duì)象都會(huì)有一個(gè) isa 的成員變量[公共繼承].而該 isa 變量指向該對(duì)象的類(圖3.15)[類在Objective-C中也是一個(gè)實(shí)體, 由于存在Objective-C 運(yùn)行環(huán)境所有的類將有自己的存儲(chǔ)空間.Objective-C 運(yùn)行環(huán)境將為每個(gè)類分配空間. 這里 所說的 isa,正是指向這樣一個(gè)類的空間. 從而建立類和對(duì)象之間的對(duì)應(yīng)關(guān)系.] 類空間 包含了該類定義的成員變量,以及方法實(shí)現(xiàn), 還包含了指向自己父類空間的指針. 


方法以 selector 作為索引. selector 的數(shù)據(jù)類型是 SEL. 雖然 SEL 定義成 char*, 我們可 以把它想象成 int. 每個(gè)方法的名字對(duì)應(yīng)一個(gè)唯一的 int 值.比如, 方法 addObject: 可能 對(duì)應(yīng)的是 12. 當(dāng)尋找該方法是, 使用的是 selector,而不是名字 @"addObject:"

Objective-C 數(shù)據(jù)結(jié)構(gòu)中,存在一個(gè) name - selector 的映射表如圖 3.16 



在編譯的時(shí)候, 只要有方法的調(diào)用, 編譯器都會(huì)通過 selector 來查找,所以 (假設(shè) addObject 的 selector 為 12)

 [myObject addObject:yourObject]; 

將會(huì)編譯變成

objc_msgSend(myObject, 12, yourObject);

這里,objec_msgSend()函數(shù)將會(huì)使用 myObjec 的 isa 指針來找到 myObject 的類空間結(jié)構(gòu)并 在類空間結(jié)構(gòu)中查找 selector 12 所對(duì)應(yīng)的方法.如果沒有找到,那么將使用指向父類的指 針找到父類空間結(jié)構(gòu)進(jìn)行 selector 12 的查找. 如果仍然沒有找到,就繼續(xù)往父類的父類一 直找,直到找到為止, 如果到了根類 NSObject 中仍然找不到,將會(huì)拋出異常.

我們可以看到, 這是一個(gè)很動(dòng)態(tài)的查找過程.類的結(jié)構(gòu)可以在運(yùn)行的時(shí)候改變,這樣可以很 容易來進(jìn)行功能擴(kuò)展[Objective-C 語言是動(dòng)態(tài)語言, 支持動(dòng)態(tài)綁定.


再來看

Objective-C如何獲取消息的原理詳解文章

Objective-C獲取消息工作原理是本文要介紹的內(nèi)容,看name mangling的時(shí)候,也講到了Objective-C的name mangling,于是又重新讀了一下Objective-C 2.0 programming Language以及Objective-C 2.0 Runtime Reference里的相關(guān)內(nèi)容,自己歸納一下。

先貼一段代碼:

  1. MyClass.h    
  2.    @interface MyClass : NSObject    
  3.    {    
  4.     }    
  5.    @end    
  6.    MyClass.m    
  7.    #import    
  8.    #import “MyClass.h”    
  9.    void myClassIMP(id _rec, SEL _cmd, int theInt)    
  10.    {    
  11.       NSLog(@”dynamic added method:%d”,theInt);    
  12.    }    
  13.       
  14. - (id)init    
  15. {    
  16.     if( ( self = [super init]) != nil )    
  17.     {    
  18.    class_addMethod([MyClass class], @selector(dynGeneratedMethod:),(IMP)myClassIMP,”v@:i”);    
  19.      }    
  20.     return self;    
  21. }    
  22.     
  23. Main.c    
  24. #import “MyClass.h”    
  25. int main(int argc, char *argv[])    
  26. {    
  27.   MyClass theInstance = [[MyClass alloc] init];    
  28.   [theInstance dynGeneratedMethod:10];    
  29.  return 0;    
  30. }  

這段代碼執(zhí)行的結(jié)果是在控制臺(tái)上輸出:

dynamic added method:10

接著來詳細(xì)分析一下上面的代碼:

在ObjC的類中這樣的一個(gè)聲明 – (void)foo:(int)a,;被稱作方法(method),而在調(diào)用的地方: [theClass foo:10];則被稱之為發(fā)送消息(send message),具體來說是給對(duì)象theClass 發(fā)送foo:消息,注意這里foo后面的”:”,它也是消息名稱的一部分,,最前面的'-'代表實(shí)例方法,,'+'代表類方法。而類似的語句,,在C或C++ 中,,通常被稱為呼叫函數(shù)(call function),在ObjC中,函數(shù)(function)一詞很少用到,不是它不存在,,而是它被ObjC runtime給隱藏了起來,。

如前所述,ObjC是以消息機(jī)制來工作的,,但其實(shí)諸如-(void)foo:(int)a的語句在編譯時(shí)被 objc_msgSend(receiver,selector,arg1,arg2,….)替換了,,所以其實(shí)每一條發(fā)送消息的代碼本質(zhì)上還是調(diào)用函數(shù) (call function),不過他們調(diào)用的都是同一個(gè)函數(shù)objc_msgSend(也可能是objc_msgSend_stret(返回值是結(jié)構(gòu) 體),objc_msgSend_fpret(返回值是浮點(diǎn)型)等)

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

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

因?yàn)?strong>消息的接受對(duì)象和接受對(duì)象的方法都參數(shù)化,所以在運(yùn)行時(shí)刻,,接受對(duì)象和接受對(duì)象的方法都可以是動(dòng)態(tài)的!

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

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

它的實(shí)現(xiàn)是基于ObjC runtime. NSObject類實(shí)現(xiàn)了這套機(jī)制,,所以每一個(gè)繼承于NSObject的類都能自動(dòng)獲得runtime的支持。在這樣的一個(gè)類中,,有一個(gè)isa指針,,指向 該類定義的數(shù)據(jù)結(jié)構(gòu)體,這個(gè)結(jié)構(gòu)體是由編譯器編譯時(shí)為類(須繼承于NSObject)創(chuàng)建的.在這個(gè)結(jié)構(gòu)體中有包括了指向其父類類定義的指針以及 Dispatch table. Dispatch table是一張SEL和IMP的對(duì)應(yīng)表。

對(duì)于名稱相同的方法,,他們都有相同的SEL,方法的名稱不包括類名稱,,所以子類和父類中的同名方法擁有相同的SEL,但是他們的實(shí)現(xiàn)可以各不相同, 因而在他們各自的Dispatch表中SEL所對(duì)應(yīng)的IMP是不同的,,IMP是一個(gè)函數(shù)指針,,而雖然每一個(gè)SEL對(duì)應(yīng)的是一個(gè)方法的名稱,但考慮到效 率,,SEL本身是一個(gè)整型,,編譯器會(huì)另外生成一張SEL和方法名稱對(duì)應(yīng)的表。有了這樣的結(jié)構(gòu),,objc就可以實(shí)現(xiàn)多態(tài)了,。還是這行代碼:

[theClass foo:10];

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

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

就是給MyClass類在執(zhí)行時(shí)刻增加了一個(gè)響應(yīng)dynGeneratedMethod:消息的方法,這樣之后對(duì)任何MyClass的instance類 發(fā)送dynGeneratedMethod:消息,,就會(huì)得到響應(yīng)了.myClassIMP是類收到該消息時(shí)要調(diào)用的方法,,其聲明如下:

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

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

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

幾個(gè)要點(diǎn):

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

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

我感覺ObjC這樣的一套sender receiver的定義更注重面向?qū)ο蟮母拍?。類是一個(gè)接收者(receiver),,如果定義了某個(gè)方法,就可以接收和這個(gè)方法名稱相同的消息,。而使用該 類的client(sender),則嘗試向該類發(fā)送消息.如果匹配了,,就跳到類的方法里執(zhí)行。

2,、方法名稱是諸如foo:,,不包括返回類型,參數(shù)類型,,而又因?yàn)橐粋€(gè)foo:對(duì)應(yīng)于一個(gè)SEL,,所以說ObjC不支持相同的foo:有不同的返回 類型,也不支持重載,。不過類方法和實(shí)例方法可以有相同的名字,,而又有不同類型的參數(shù)和返回類型,因?yàn)樗鼈儾皇翘幵谕粡坉ispatch table中。

3,、不僅類的方法可以運(yùn)行時(shí)刻創(chuàng)建,,類本身也可以在運(yùn)行時(shí)刻創(chuàng)建,前面提到繼承于NSObject的類,編譯器會(huì)幫忙生成ObjC runtime所需要的類結(jié)構(gòu)定義,,只要我們?cè)诖a里也按照那個(gè)結(jié)構(gòu)創(chuàng)建了自己的類,,那一樣可以獲得ObjC runtime的支持。



    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多