2018-05-09

????????????????????????????????????????????????????????????????????????????????????關(guān)于數(shù)組越界的系統(tǒng)崩潰的問(wèn)題



小伙伴門(mén)經(jīng)常見(jiàn)到這個(gè)崩潰日志吧!! ?能不能不不讓系統(tǒng)不直接崩潰,進(jìn)而影響用戶體驗(yàn)!Q┍辍!研究了下runtime 機(jī)制可以完美解決這個(gè)問(wèn)題灰瞻!讓它不會(huì)因?yàn)閿?shù)組越界而崩潰,并且抓取報(bào)錯(cuò)的堆棧信息~~~~???? ?個(gè)人 建議:當(dāng)我們?cè)跍y(cè)試環(huán)境下最好不要用這個(gè)!!因?yàn)楸M量減少奔潰的問(wèn)題,并修復(fù)~~~~ ?對(duì)那些已經(jīng)是正式環(huán)境下可以用一下,不會(huì)因?yàn)殡[藏在深處的問(wèn)題導(dǎo)致系統(tǒng)直接崩潰,進(jìn)而影響用戶體驗(yàn)~~~~~~同時(shí)最好能上傳報(bào)錯(cuò)日志余境,我們可以方便找到出錯(cuò)的地方并且修復(fù)! ?我們公司用的是騰訊的Bugly 框架~~感興趣的童鞋可以集成一下~~~?? ?Bugly 飛機(jī)地址~~~


數(shù)組越界再熟悉不過(guò)了



利用runtime 交換系統(tǒng)的方法 ~~~~ ? ? 實(shí)現(xiàn)思路:當(dāng)我們對(duì)數(shù)組取值的時(shí)候會(huì)調(diào)用以下兩種任意的一種的方法 !那么我們可以用runtime 的機(jī)制替換掉系統(tǒng)的方法灌诅,轉(zhuǎn)換為我們自定義的方法芳来,對(duì)自定義方法里面對(duì)數(shù)組進(jìn)行判斷!Q铀堋绣张!如果越界了 就拋出異常答渔!

? ? NSArray*arr =@[@"1",@"2"];

? ? NSLog(@"%@",arr[10]); ?//這個(gè)方法就是 [arr ?objectAtIndexedSubscript : 10 ] ?的縮寫(xiě)

? ? NSLog(@"%@",[arr objectAtIndex:10]);

OK 下面貼出代碼


創(chuàng)建一個(gè)NSObject 分類(lèi)

.h實(shí)現(xiàn)



/**

?替換系統(tǒng)方法 所有的成員方法

?@param originalSelector 系統(tǒng)的方法

?@param swizzledSelector 自定義的方法

?@return? NO表示沒(méi)有找到該方法

?*/

+ (BOOL)swizzleMethod:(SEL)originalSelector withMethod:(SEL)swizzledSelector?

{

? ? MethodoriginalMethod =class_getInstanceMethod(self, originalSelector);

? ? if(!originalMethod) {

? ? ? ? NSString*string = [NSStringstringWithFormat:@"系統(tǒng)的: %@ 類(lèi)沒(méi)有找到 %@ 方法",NSStringFromClass([selfclass]),NSStringFromSelector(originalSelector)];

? ? ? ? NSLog(@"%@",string);

? ? ? ? returnNO;

? ? }

? ? MethodswizzledMethod =class_getInstanceMethod(self, swizzledSelector);


? ? if(!swizzledMethod) {

? ? ? ? NSString*string = [NSStringstringWithFormat:@"自定義: %@ 類(lèi)沒(méi)有找到 %@ 方法",NSStringFromClass([selfclass]),NSStringFromSelector(swizzledSelector)];

?? ? ? ? NSLog(@"%@",string);

? ? ? ? returnNO;

? ? }


? ? if(class_addMethod(self, originalSelector,method_getImplementation(swizzledMethod),method_getTypeEncoding(swizzledMethod)))

? ? {

? ? ? ? class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));

? ? }else{

? ? ? ? method_exchangeImplementations(originalMethod, swizzledMethod);

? ? }

? ? return YES;

}

/**

?替換系統(tǒng)方法

?@param originalSelector 系統(tǒng)的方法

?@param iswizzleMethod YES 表示系統(tǒng)方法 為類(lèi)方法 ; 表示成員方法

?@param swizzledSelector 自定義的方法

?@param iswithMethod YES 表示自定義方法 為類(lèi)方法 ; 表示成員方法

?@return NO表示沒(méi)有找到該方法

*/

+ (BOOL)swizzleMethod:(SEL)originalSelector IswizzleMethod:(BOOL)iswizzleMethod? withMethod:(SEL)swizzledSelector? IswithMethod:(BOOL)iswithMethod

{?

//? class_getClassMethod? 為類(lèi)方法? ? ? class_getInstanceMethod? 表示成員方法

? ? MethodoriginalMethod =? iswizzleMethod==YES?class_getClassMethod(self, originalSelector):class_getInstanceMethod(self, originalSelector);

? ? if(!originalMethod) {


? ? ? ? NSString*string = [NSStringstringWithFormat:@"系統(tǒng)的: %@ 類(lèi)沒(méi)有找到 %@ 方法",NSStringFromClass([selfclass]),NSStringFromSelector(originalSelector)];


? ? ? ? NSLog(@"%@",string);


? ? ? ? returnNO;

? ? }

? ? MethodswizzledMethod = iswithMethod==YES?class_getClassMethod(self, swizzledSelector):class_getInstanceMethod(self, swizzledSelector);

? ? if(!swizzledMethod) {


? ? ? ? NSString*string = [NSStringstringWithFormat:@"自定義: %@ 類(lèi)沒(méi)有找到 %@ 方法",NSStringFromClass([selfclass]),NSStringFromSelector(swizzledSelector)];


? ? ? ? NSLog(@"%@",string);


? ? ? ? returnNO;

? ? }


? ? if(class_addMethod(self, originalSelector,method_getImplementation(swizzledMethod),method_getTypeEncoding(swizzledMethod)))

? ? {

? ? ? ? class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));

? ? }else{

? ? ? ? method_exchangeImplementations(originalMethod, swizzledMethod);

? ? }

? ? return YES;



}



新建個(gè)NSArray 分類(lèi) ? ?.m實(shí)現(xiàn) ??


+ (void)load

{

? ?//替換不可變數(shù)組方法 取數(shù)組下標(biāo)時(shí)應(yīng)該替換 ?swizzleMethod 為系統(tǒng)的方法 ??withMethod 為自定義方法

? ? ? [objc_getClass("__NSArrayI")swizzleMethod:@selector(objectAtIndexedSubscript:)withMethod:@selector(FJL_ObjectAtIndexedSubscript:)];

? ? //替換不可變數(shù)組只有一個(gè)元素的時(shí)候

?? ? [objc_getClass("__NSSingleObjectArrayI")swizzleMethod:@selector(objectAtIndex:)withMethod:@selector(FJL_objectAtIndex:)];

? ? //替換可變數(shù)組方法 取數(shù)組下標(biāo)時(shí)應(yīng)該替換

?? ? [objc_getClass("__NSArrayM")swizzleMethod:@selector(objectAtIndexedSubscript:)withMethod:@selector(FJL_mutableObjectAtIndexedSubscript:)];

? ? //替換可變數(shù)組方法

?? ? [objc_getClass("__NSArrayM")swizzleMethod:@selector(objectAtIndex:)withMethod:@selector(FJL_mutableobjectAtIndex:)];

}

- (id)FJL_objectAtIndex:(NSUInteger)index

{

? ? if(index >self.count-1|| !self.count) {

? ? ? ? @try{

? ? ? ? ? ? return[selfFJL_objectAtIndex:index]; //注意:此處并沒(méi)有遞歸操作. 因?yàn)榻粨Q了系統(tǒng)的方法

? ? ? ? }

? ? ? ? @catch(NSException *exception) {

? ? ? ? ? ? NSLog(@"exception==== %@", exception); //異常信息

? ? ? ? ? ? // 拋出異常方式

? ? ? ? ? ? ? // [Bugly reportException:exception];//我上傳的是騰訊的崩潰日志

? ? ? ? ? ? returnnil;

? ? ? ? }


? ? }else{

? ? ? ? return[self FJL_objectAtIndex:index];?//注意:此處并沒(méi)有遞歸操作. 因?yàn)榻粨Q了系統(tǒng)的方法

? ? }

}

- (id)FJL_mutableobjectAtIndex:(NSUInteger)index

{

? ? if(index >self.count-1|| !self.count) {

? ? ? ? @try{

? ? ? ? ? ? return [self FJL_mutableobjectAtIndex:index];??//注意:此處并沒(méi)有遞歸操作. 因?yàn)榻粨Q了系統(tǒng)的方法

? ? ? ? }

? ? ? ? @catch(NSException *exception) {

? ? ? ? ? ? NSLog(@"exception====: %@", exception.reason);

?? ? ? ? ? // 拋出異常方式

? ? ? ? ? // ?[Bugly reportException:exception];//上報(bào)崩潰日志

? ? ? ? ? ? returnnil;

? ? ? ? }


? ? }else{

? ? ? ? return [self FJL_mutableobjectAtIndex:index];??//注意:此處并沒(méi)有遞歸操作. 因?yàn)榻粨Q了系統(tǒng)的方法

? ? }

}

- (id)FJL_ObjectAtIndexedSubscript:(NSUInteger)index

{

? ? if(index >self.count-1|| !self.count) {

? ? ? ? @try{

? ? ? ? ? ? return [self FJL_ObjectAtIndexedSubscript:index];??//注意:此處并沒(méi)有遞歸操作. 因?yàn)榻粨Q了系統(tǒng)的方法

? ? ? ? }

? ? ? ? @catch(NSException *exception) {

? ? ? ? ? ? NSLog(@"exception====: %@", exception.reason);

? ? ? ? ? ? // 拋出異常方式

? ? ? ? ?// ?[Bugly reportException:exception];//上報(bào)崩潰日志

? ? ? ? ? ? returnnil;

? ? ? ? }


? ? }else{

? ? ? ? return [self FJL_ObjectAtIndexedSubscript:index];??//注意:此處并沒(méi)有遞歸操作. 因?yàn)榻粨Q了系統(tǒng)的方法

? ? }

}

- (id)FJL_mutableObjectAtIndexedSubscript:(NSUInteger)index

{

? ? if(index >self.count-1|| !self.count) {

? ? ? ? @try{

? ? ? ? ? ? return [self FJL_mutableObjectAtIndexedSubscript:index];??//注意:此處并沒(méi)有遞歸操作. 因?yàn)榻粨Q了系統(tǒng)的方法

? ? ? ? }

? ? ? ? @catch(NSException *exception) {

? ? ? ? ? ? NSLog(@"exception====: %@", exception.reason);

? ? ? ? ? // ?[Bugly reportException:exception];//上報(bào)崩潰日志

? ? ? ? ? ? returnnil;

? ? ? ? }


? ? }else{

? ? ? ? return [self FJL_mutableObjectAtIndexedSubscript:index];??//注意:此處并沒(méi)有遞歸操作. 因?yàn)榻粨Q了系統(tǒng)的方法

? ? }

}

OK ?以上就是所有的源碼 ? ?用著有問(wèn)題歡迎@我哈


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末关带,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子沼撕,更是在濱河造成了極大的恐慌宋雏,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,029評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件务豺,死亡現(xiàn)場(chǎng)離奇詭異磨总,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)笼沥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)蚪燕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人奔浅,你說(shuō)我怎么就攤上這事馆纳。” “怎么了汹桦?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,570評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵鲁驶,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我舞骆,道長(zhǎng)钥弯,這世上最難降的妖魔是什么径荔? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,535評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮脆霎,結(jié)果婚禮上总处,老公的妹妹穿的比我還像新娘。我一直安慰自己睛蛛,他們只是感情好辨泳,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,650評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著玖院,像睡著了一般菠红。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上难菌,一...
    開(kāi)封第一講書(shū)人閱讀 49,850評(píng)論 1 290
  • 那天试溯,我揣著相機(jī)與錄音,去河邊找鬼郊酒。 笑死遇绞,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的燎窘。 我是一名探鬼主播摹闽,決...
    沈念sama閱讀 39,006評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼褐健!你這毒婦竟也來(lái)了付鹿?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,747評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蚜迅,失蹤者是張志新(化名)和其女友劉穎舵匾,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體谁不,經(jīng)...
    沈念sama閱讀 44,207評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡坐梯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,536評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了刹帕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吵血。...
    茶點(diǎn)故事閱讀 38,683評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖偷溺,靈堂內(nèi)的尸體忽然破棺而出蹋辅,到底是詐尸還是另有隱情,我是刑警寧澤亡蓉,帶...
    沈念sama閱讀 34,342評(píng)論 4 330
  • 正文 年R本政府宣布晕翠,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏淋肾。R本人自食惡果不足惜硫麻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,964評(píng)論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望樊卓。 院中可真熱鬧拿愧,春花似錦、人聲如沸碌尔。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,772評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)唾戚。三九已至柳洋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間叹坦,已是汗流浹背熊镣。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,004評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留募书,地道東北人绪囱。 一個(gè)月前我還...
    沈念sama閱讀 46,401評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像莹捡,于是被迫代替她去往敵國(guó)和親鬼吵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,566評(píng)論 2 349

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉篮赢,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,690評(píng)論 0 9
  • 轉(zhuǎn)載:http://www.cocoachina.com/ios/20161102/17920.html 因?yàn)镺b...
    F麥子閱讀 665評(píng)論 0 1
  • 轉(zhuǎn)載:http://yulingtianxia.com/blog/2014/11/05/objective-c-r...
    F麥子閱讀 729評(píng)論 0 2
  • 本文詳細(xì)整理了 Cocoa 的 Runtime 系統(tǒng)的知識(shí)齿椅,它使得 Objective-C 如虎添翼,具備了靈活的...
    lylaut閱讀 795評(píng)論 0 4
  • 我們常常會(huì)聽(tīng)說(shuō) Objective-C 是一門(mén)動(dòng)態(tài)語(yǔ)言荷逞,那么這個(gè)「動(dòng)態(tài)」表現(xiàn)在哪呢媒咳?我想最主要的表現(xiàn)就是 Obje...
    Ethan_Struggle閱讀 2,182評(píng)論 0 7