Runtime

[obj message]調(diào)用執(zhí)行過程如下圖:


1456815016258663.png

一個函數(shù)是由一個selector(SEL),和一個implement(IML)組成的汪疮。Selector相當于門牌號峭火,而Implement才是真正的住戶(函數(shù)實現(xiàn))。
一個OC對象執(zhí)行[obj message]方法后智嚷,如果message并沒有被obj所屬類實現(xiàn)卖丸,會報unrecognized selector sent to instance錯誤,runtime給了我們3次機會去避免發(fā)生這樣的情況盏道。
1.OC對象在收到無法解讀的消息后稍浆,首先會調(diào)用所屬類的+ (BOOL)resolveInstanceMethod:(SEL)sel,這個方法在運行時,沒有找到SEL的IML時就會執(zhí)行猜嘱。這個函數(shù)是給實例對象利用class_addMethod添加函數(shù)的機會衅枫。根據(jù)文檔,如果實現(xiàn)了添加函數(shù)代碼則返回YES朗伶,未實現(xiàn)返回NO弦撩。resolveClassMethod:是用于動態(tài)解析一個類方法;而resolveInstanceMethod:是用于動態(tài)解析一個實例方法论皆。

//類函數(shù)
+ (BOOL) resolveInstanceMethod:(SEL)aSEL
{
    if (aSEL == @selector(resolveThisMethodDynamically))
    {
          class_addMethod([self class], aSEL, (IMP) dynamicMethodIMP, "v@:");
          return YES;
    }
    return [super resolveInstanceMethod:aSel];
}```
關于class_addMethod這個方法益楼,是這樣定義的

OBJC_EXPORT BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)
cls 在這個類中添加方法猾漫,也就是方法所添加的類
name 方法名,這個可以隨便起的
imp 實現(xiàn)這個方法的函數(shù)
types 定義該數(shù)返回值類型和參數(shù)類型的字符串感凤,這里比如"v@:"悯周,其中v就是void,帶表返回類型就是空陪竿,@代表參數(shù)禽翼,這里指的是id(self),這里:指的是方法SEL(_cmd)族跛,比如再定義一個函數(shù)
int newMethod (id self, SEL _cmd, NSString *str) {

return 100;
}
那么添加這個函數(shù)的方法就應該是ass_addMethod([self class], @selector(newMethod), (IMP)newMethod, "i@:@");

2.如果在+ (BOOL)resolveInstanceMethod:(SEL)sel中沒有找到或者添加方法闰挡,消息繼續(xù)往下傳遞到`- (id)forwardingTargetForSelector:(SEL)aSelector`看看是不是有對象可以執(zhí)行這個方法,該方法返回未被接收消息最先被轉(zhuǎn)發(fā)到的對象庸蔼。如果一個對象實現(xiàn)了這個方法,并返回一個非空的對象(且非對象本身)贮匕,則這個被返回的對象成為消息的新接收者姐仅。另外如果在非根類里面實現(xiàn)這個方法,如果對于給定的selector刻盐,我們沒有可用的對象可以返回掏膏,則應該調(diào)用父類的方法實現(xiàn),并返回其結果敦锌。

//將消息轉(zhuǎn)出某對象

  • (id)forwardingTargetForSelector:(SEL)aSelector
    {
    NSLog(@"MyTestObject _cmd: %@", NSStringFromSelector(_cmd));

    NoneClass *none = [[NoneClass alloc] init];
    if ([none respondsToSelector: aSelector]) {
    return none;
    }

    return [super forwardingTargetForSelector: aSelector];
    }

3.當前面兩步都無法處理消息時馒疹,運行時系統(tǒng)便會給接收者最后一個機會,將其轉(zhuǎn)發(fā)給其它代理對象來處理乙墙。這主要是通過創(chuàng)建一個表示消息的`NSInvocation`對象并將這個對象當作參數(shù)傳遞給`forwardInvocation:`方法颖变。我們在`forwardInvocation:`方法中可以選擇將消息轉(zhuǎn)發(fā)給其它對象。
在這個方法中听想,主要是需要做兩件事:
(1).找到一個能處理anInvocation調(diào)用的對象腥刹。
(2).將消息以anInvocation的形式發(fā)送給對象。anInvocation將維護調(diào)用的結果汉买,而運行時則會將這個結果返回給消息的原始發(fā)送者衔峰。

真正執(zhí)行從 `methodSignatureForSelector:`返回的NSMethodSignature。這個函數(shù)讓重載方有機會拋出一個函數(shù)的簽名蛙粘,再由后面的forwardInvocation:去執(zhí)行垫卤。在這個函數(shù)里可以將NSInvocation多次轉(zhuǎn)發(fā)到多個對象中,這也是這種方式靈活的地方出牧。(forwardingTargetForSelector只能以Selector的形式轉(zhuǎn)向一個對象)
  • (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
    {
    NSString *sel = NSStringFromSelector(selector);
    if ([sel rangeOfString:@"set"].location == 0) {
    //動態(tài)造一個 setter函數(shù)
    return [NSMethodSignature signatureWithObjCTypes:"v@:@"];
    } else {
    //動態(tài)造一個 getter函數(shù)
    return [NSMethodSignature signatureWithObjCTypes:"@@:"];
    }
    }

  • (void)forwardInvocation:(NSInvocation *)invocation
    {
    //拿到函數(shù)名
    NSString *key = NSStringFromSelector([invocation selector]);
    if ([key rangeOfString:@"set"].location == 0) {
    //setter函數(shù)形如 setXXX: 拆掉 set和冒號
    key = [[key substringWithRange:NSMakeRange(3, [key length]-4)] lowercaseString];
    NSString *obj;
    //從參數(shù)列表中找到值
    [invocation getArgument:&obj atIndex:2];
    [data setObject:obj forKey:key];
    } else {
    //getter函數(shù)就相對簡單了穴肘,直接把函數(shù)名做 key就好了。
    NSString *obj = [data objectForKey:key];
    [invocation setReturnValue:&obj];
    }
    }


`- (void)doesNotRecognizeSelector:(SEL)aSelector`
作為找不到函數(shù)實現(xiàn)的最后一步舔痕,NSObject實現(xiàn)這個函數(shù)只有一個功能梢褐,就是拋出異常旺遮。
雖然理論上可以重載這個函數(shù)實現(xiàn)保證不拋出異常(不調(diào)用super實現(xiàn)),但是蘋果文檔著重提出“一定不能讓這個函數(shù)就這么結束掉盈咳,必須拋出異彻⒚迹”。
#使用場景:
在一個函數(shù)找不到時鱼响,Objective-C提供了三種方式去補救:
1鸣剪、調(diào)用resolveInstanceMethod給個機會讓類添加這個實現(xiàn)這個函數(shù)
2、調(diào)用forwardingTargetForSelector讓別的對象去執(zhí)行這個函數(shù)
3丈积、調(diào)用methodSignatureForSelector(函數(shù)符號制造器)和forwardInvocation(函數(shù)執(zhí)行器)靈活的將目標函數(shù)以其他形式執(zhí)行筐骇。
如果都不中,調(diào)用doesNotRecognizeSelector拋出異常江滨。

參考:
http://www.cocoachina.com/ios/20160302/15494.html
http://www.cnblogs.com/biosli/p/NSObject_inherit_2.html
http://www.cocoachina.com/ios/20150205/11113.html
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末铛纬,一起剝皮案震驚了整個濱河市坚洽,隨后出現(xiàn)的幾起案子糜烹,更是在濱河造成了極大的恐慌筛武,老刑警劉巖僚楞,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件敷存,死亡現(xiàn)場離奇詭異部蛇,居然都是意外死亡窍帝,警方通過查閱死者的電腦和手機趋观,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門稻艰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來懂牧,“玉大人,你說我怎么就攤上這事尊勿∩铮” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵元扔,是天一觀的道長拼弃。 經(jīng)常有香客問我,道長摇展,這世上最難降的妖魔是什么吻氧? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮咏连,結果婚禮上盯孙,老公的妹妹穿的比我還像新娘。我一直安慰自己祟滴,他們只是感情好振惰,可當我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著垄懂,像睡著了一般骑晶。 火紅的嫁衣襯著肌膚如雪痛垛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天桶蛔,我揣著相機與錄音匙头,去河邊找鬼。 笑死仔雷,一個胖子當著我的面吹牛蹂析,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播碟婆,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼电抚,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了竖共?” 一聲冷哼從身側響起蝙叛,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎公给,沒想到半個月后借帘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡妓布,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年姻蚓,在試婚紗的時候發(fā)現(xiàn)自己被綠了宋梧。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片匣沼。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖捂龄,靈堂內(nèi)的尸體忽然破棺而出释涛,到底是詐尸還是另有隱情,我是刑警寧澤倦沧,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布唇撬,位于F島的核電站,受9級特大地震影響展融,放射性物質(zhì)發(fā)生泄漏窖认。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一告希、第九天 我趴在偏房一處隱蔽的房頂上張望扑浸。 院中可真熱鬧,春花似錦燕偶、人聲如沸喝噪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽酝惧。三九已至榴鼎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間晚唇,已是汗流浹背巫财。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留缺亮,地道東北人翁涤。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像萌踱,于是被迫代替她去往敵國和親葵礼。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 參考鏈接: http://www.cnblogs.com/ioshe/p/5489086.html 簡介 Runt...
    樂樂的簡書閱讀 2,137評論 0 9
  • 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的...
    西木閱讀 30,567評論 33 466
  • 本文詳細整理了 Cocoa 的 Runtime 系統(tǒng)的知識并鸵,它使得 Objective-C 如虎添翼鸳粉,具備了靈活的...
    lylaut閱讀 806評論 0 4
  • 我們常常會聽說 Objective-C 是一門動態(tài)語言,那么這個「動態(tài)」表現(xiàn)在哪呢园担?我想最主要的表現(xiàn)就是 Obje...
    Ethan_Struggle閱讀 2,199評論 0 7
  • 轉(zhuǎn)載:http://yulingtianxia.com/blog/2014/11/05/objective-c-r...
    F麥子閱讀 735評論 0 2