用runtime處理 unrecognized selector sent to

*問題:調(diào)用的方法找不到會怎么辦?

People *people = [[Book alloc]init];

[people eat];

上面兩句代碼中,People類有一個eat的方法傲茄,但People *people = [[Book alloc]init];返回的people是一個people,這時候people再去執(zhí)行eat方法赂毯,程序就會Carsh怀跛,并會拋出unrecognized selector sent to 的錯誤,空IMP(指針錯誤)相叁,因為Book類里面沒有eat的方法遵绰。

對于這種錯誤,一般的處理處理方式是改變people實現(xiàn)的代碼增淹,讓他生成正確的類型椿访,今天我們來講講另外的一種預(yù)防處理機制,我們暫把它叫做空IMP的runtime處理法

在runtime的機制中虑润,程序在運行時成玫,如果執(zhí)行到IMP的對象時,在拋出unrecognized selector sent to錯誤之前拳喻,程序還會執(zhí)行三個方法哭当,我們暫且稱為空指針三步走。

主要用到objc.h的四個方法:

+ (BOOL)resolveInstanceMethod:(SEL)selOBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);

- (id)forwardingTargetForSelector:(SEL)aSelector OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector OBJC_SWIFT_UNAVAILABLE("");

- (void)forwardInvocation:(NSInvocation *)anInvocation OBJC_SWIFT_UNAVAILABLE("");

這四個方法為我們提供了三種補救方案冗澈,

第一種方案:Resolution嘗試新的解決方案钦勘,若有方案,則重啟消息發(fā)送流程亚亲,代碼如下

+ (BOOL)resolveInstanceMethod:(SEL)sel

{

if([NSStringFromSelector(sel) isEqualToString:eat]){

class_addMethod(self.class,NSSelectorFromString(eat), (IMP)eat,"@:");//給對象添加一個方法

return [super resolveInstanceMethod:sel];//重新發(fā)送

}

return NO;

}

上面代碼中彻采,我們在條件檢測中去辨別是不是我們要處理的方法,如果是捌归,我們就用runtime動態(tài)增加一個新方法肛响,并重啟消息發(fā)送機制[super resolveInstanceMethod:sel],如不是我們要處理的方法惜索,則返回NO特笋。

如果在這一步中返回值不為NO,則系統(tǒng)就根據(jù)根據(jù)返回的方法去重新處理门扇,如返回NO雹有,則進去第二部偿渡,實行第二種解決方案

第二種解決方案

//Fast Forwarding向前尋找處理對象

- (id)forwardingTargetForSelector:(SEL)aSelector

{

if([NSStringFromSelector(aSelector) isEqualToString:@"eat"]){

People *people = [[People alloc]init];

NSLog(@"新生成一個People對象%@,讓他來幫我們完成eat的動作",people);

return people;//返回新的對象霸奕,讓心的對象去執(zhí)行新對象中的eat方法

}

return nil;

}

上面代碼中溜宽,我們在條件檢測中去辨別是不是我們要處理的方法,如果是质帅,我們就新生成一個正確的對象peopple适揉,返回新對象peopple,讓新對象peopple去執(zhí)行eat煤惩,如不是我們要處理的方法嫉嘀,則返回nil。

如果這一步?jīng)]有返回對象魄揉,則進去第三種解決方案

第三種解決方案


//Normal Forwarding 這個解決方案又分為兩步走

//第一步

-(NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector

{

if([NSStringFromSelector(aSelector) isEqualToString:@"eat"]){

//是我們要處理的方法

//第一步生成方法信號剪侮,告訴系統(tǒng)我們找到了這個方法的處理方式了

NSMethodSignature *methodSignature = [super methodSignatureForSelector:aSelector];

if(!methodSignature) {

methodSignature = [NSMethod SignaturesignatureWithObjCTypes:"v@:*"];

}

returnmethodSignature;

}

NSLog(@"沒有這個方法的處理方式");

return nil;//返回nil的時候,系統(tǒng)就會拋出unrecognized selector sent to的錯誤洛退。

}

//第二步

- (void)forwardInvocation:(NSInvocation*)anInvocation

{

if([NSStringFromSelector(anInvocation.selector) isEqualToString:@"eat"]){

People *people = [[People alloc]init];//新生成對象

if([people respondsToSelector:anInvocation.selector]) {//判斷對象是否能處理該方法

[anInvocation invokeWithTarget:people];//把動作交給新的對象people去完成

}

}

}

上面代碼瓣俯,第一步中,我們在條件檢測中去辨別是不是我們要處理的方法兵怯,如果是彩匕,則需返回一個信號告訴系統(tǒng),找到處理方式了媒区,如不是我們要處理的方法驼仪,則返回nil,讓系統(tǒng)拋出unrecognized selector sent to的錯誤袜漩。

如果在第一步中有返回信號绪爸,則系統(tǒng)就會執(zhí)行第二步的方法,系統(tǒng)跑到forwardInvocation:
后宙攻,我們調(diào)用[anInvocation invokeWithTarget:people];幫方法的處理者替換掉

*注意毡泻,如果在第一步中有返回信號,系統(tǒng)就不再會拋出unrecognized selector sent to的錯誤粘优,即不管是否實現(xiàn)了第二步,程序都不會奔潰了呻顽。


說了那么多雹顺,這究竟有什么用?

1.退一步處理原則:奔潰是最不好的一種體驗廊遍,就算我們沒有完成用戶的動作嬉愧,最好也不要讓程序奔潰,這里你可以報提示或?qū)㈠e誤信息提交至服務(wù)器喉前。

2.動態(tài)修復(fù)没酣,程序發(fā)布時預(yù)留runtiem處理接口王财,分析服務(wù)器接收到的錯誤信息,利用runtiem進行修復(fù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末裕便,一起剝皮案震驚了整個濱河市绒净,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌偿衰,老刑警劉巖挂疆,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異下翎,居然都是意外死亡缤言,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門视事,熙熙樓的掌柜王于貴愁眉苦臉地迎上來胆萧,“玉大人,你說我怎么就攤上這事俐东〉耄” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵犬性,是天一觀的道長瞻离。 經(jīng)常有香客問我,道長乒裆,這世上最難降的妖魔是什么套利? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮鹤耍,結(jié)果婚禮上肉迫,老公的妹妹穿的比我還像新娘。我一直安慰自己稿黄,他們只是感情好喊衫,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著杆怕,像睡著了一般族购。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上陵珍,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天寝杖,我揣著相機與錄音,去河邊找鬼互纯。 笑死瑟幕,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播只盹,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼辣往,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了殖卑?” 一聲冷哼從身側(cè)響起站削,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎懦鼠,沒想到半個月后钻哩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡肛冶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年街氢,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片睦袖。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡珊肃,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出馅笙,到底是詐尸還是另有隱情伦乔,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布董习,位于F島的核電站烈和,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏皿淋。R本人自食惡果不足惜招刹,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望窝趣。 院中可真熱鬧疯暑,春花似錦、人聲如沸哑舒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽洗鸵。三九已至越锈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間膘滨,已是汗流浹背瞪浸。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留吏祸,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像贡翘,于是被迫代替她去往敵國和親蹈矮。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

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