OC Exception

背景:

最近在整理bugly上的問題,順便整理記錄下來,方便后面開發(fā)的時候避免犯一樣的錯誤.ios現(xiàn)在的系統(tǒng)版本都到13點幾了,而我們app之前支持到ios8,后面升級到ios10.所以我們解決的問題主要還是針對ios10及以上.在解決問題的同時發(fā)現(xiàn)ios11以下也就是ios10點多有很大的差別.或者說ios11開始系統(tǒng)做了好多容錯處理,好多本來應(yīng)該閃退的在11及以上版本都不閃退了.如后面會提到的OKV坏为、通知等監(jiān)聽,鍵盤和數(shù)組safe的沖突導(dǎo)致的閃退.

關(guān)于NSExceptionName:

常見的就4種,其他的至少在我們項目沒見過.下面就先根據(jù)異常名字簡單翻譯理解下.

NSGenericException:一般異常

NSMallocException:內(nèi)存不足異常

NSObjectInaccessibleException:對象不可訪問異常

NSObjectNotAvailableException:對象不可用異常

NSDestinationInvalidException:目標(biāo)無效異常

NSPortTimeoutException:端口超時異常

NSInvalidSendPortException:無效發(fā)送端口異常

NSInvalidReceivePortException:無效接收端口異常

NSPortSendException:端口發(fā)送異常

NSPortReceiveException:端口接收異常

NSOldStyleException:老樣式異常

重點分享4類異常:

NSRangeException:范圍異常/越界異常

問題:

使用的數(shù)組下標(biāo)超出數(shù)組最大下標(biāo)值

比如數(shù)組長度count, index的下標(biāo)范圍[0, count -1], 在開發(fā)時,可能index的最大值超過數(shù)組的范圍

這可能是不同模塊的處理沒有對應(yīng)上

使用的數(shù)組下標(biāo)是一個非正常值

如果小標(biāo)(index)的值是由其他模塊的變量傳遞進(jìn)來的镊绪,這就會有很大的不確定性匀伏, 可能是一個很大的整數(shù)值

很明顯,上面的值分別是32位和64位下的最大整數(shù)值蝴韭,可能的情況就是傳遞的 index 參數(shù)獲取了無效的值够颠,但仍然拿到 NSMutableArray 中使用

比如 index 通過下面的方式獲取

如果找不到 str ,則返回 NSNotFound榄鉴,32位下它就是2147483647履磨,64位下18446744073709551615 蛉抓,將它作為參數(shù)傳遞則會導(dǎo)致 NSRangeException。

Cannot remove an observer for the key path"currentViewController.viewModel.selectedGoodsCount" from because it is not registered as an observer.

[self addObserver:self forKeyPath:@"currentVC.viewModel.selectedGoodsCount" options:NSKeyValueObservingOptionNew context:nil];

[self removeObserver:self forKeyPath:@"currentVC.viewModel.selectedGoodsCount"];

空數(shù)組的操作

如果一個數(shù)組剛剛初始化剃诅,還是空的巷送,就對它進(jìn)行相關(guān)讀取操作

處理的數(shù)據(jù)范圍 NSRange 超過數(shù)據(jù)本身的長度

-[__NSArrayM removeObjectsInRange:]: range {1, 1} extends beyond bounds [0 .. 0]

Cannot remove an observer for the key path"currentViewController.viewModel.selectedGoodsCount" from because it is not registered as an observer.

[self addObserver:self forKeyPath:@"currentVC.viewModel.selectedGoodsCount" options:NSKeyValueObservingOptionNew context:nil];

[self removeObserver:self forKeyPath:@"currentVC.viewModel.selectedGoodsCount"];

KVO監(jiān)聽移除了2次,或還沒添加就運行了移除,也會報數(shù)據(jù)越界.一般移除代碼會寫在dealloc方法,添加代碼比較習(xí)慣寫到viewDidLoad方法.這樣正常情況下是不會有問題的,但是極端情況下,手機卡了等情況如果導(dǎo)致你的VC創(chuàng)建了,當(dāng)沒有能加載完成顯示出來就直接回收了,就會導(dǎo)致沒有添加監(jiān)聽直接走移除監(jiān)聽而導(dǎo)致上面出現(xiàn)的閃退.所以這里給的建議是可以把監(jiān)聽的添加代碼放在init方法處理,讓生命周期對稱使用.或用runtime原理來做統(tǒng)一的交換safe保護下哪怕移除了多次監(jiān)聽也不讓閃退.

NSInvalidArgumentException:無效參數(shù)異常

1.運行時插入的Object為nil

2.或者調(diào)用一個沒有實現(xiàn)的方法

3.performSegue但是沒有在storyboard里面連線

4.返回的是id類型強轉(zhuǎn)為另外一個類型,并調(diào)用方法出現(xiàn)找不到

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason:'-[__NSDictionaryI setObject:forKey:]: unrecognized selector sent to instance 0x60000389e500'

NSString *result=@"{\"username\":\"aaa\",\"phone\":\"18273948475\",\"bankcount\":\"k3232323\"}";

NSData *data = [result dataUsingEncoding:NSUTF8StringEncoding];

NSMutableDictionary *info = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];

if (info) {

? ? ? NSString *username = info[@"username"];//[Utils UrlDecode: info[@"username"]];

? ? ? [info setObject:username forKey:@"username"];

}


從JSON數(shù)據(jù)創(chuàng)建一個Foundation對象。如果解析器應(yīng)該允許不是NSArray或NSDictionary的頂級對象矛辕,請設(shè)置NSJSONReadingAllowFragments選項笑跛。設(shè)置NSJSONReadingMutableContainers選項將使解析器生成可變NSArray和NSDictionary。設(shè)置NSJSONReadingMutableLeaves選項將使解析器生成可變的NSString對象聊品。如果在解析過程中發(fā)生錯誤堡牡,那么將設(shè)置錯誤參數(shù),結(jié)果將為零杨刨。

UITabBarController *tabBarController = (UITabBarController *)[UIApplication sharedApplication].keyWindow.rootViewController;

UINavigationController *navigationController = tabBarController.selectedViewController;

像這種強轉(zhuǎn)就要特別注意,如果當(dāng)前的rootViewController不是UITabBarController類型就會出現(xiàn)閃退.

正常寫代碼肯定不會這樣寫,但是“l(fā)oc_str”這個參數(shù)一般是上個頁面給或服務(wù)接口給的,這樣就不可控了,只要出現(xiàn)nil的情況就會閃退.

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason:'NSConcreteMutableAttributedString initWithString:: nil value'

NSString *loc_str=nil;

NSMutableAttributedString *attriutedString = [[NSMutableAttributedString alloc] initWithString:loc_str];

在對象調(diào)用了自己沒有的屬性或方法是發(fā)生的閃退:如UIView 調(diào)用了 UIViewController 的方法時發(fā)生的閃退晤柄。

一般情況下不會發(fā)生類似問題,主要是在頁面?zhèn)髦祷蛘呤褂脠?zhí)行集中跳轉(zhuǎn)邏輯的時候由于傳參不合適或者是代碼不規(guī)范造成問題妖胀。

*** -[UIWindow navigationController]: unrecognized selector sent to instance 0x101b07d60

if (! [viewController isKindOfClass:[UIViewController class]]) return;

[viewController.navigationController pushViewController:[self needJumpToVCName:vcClassName withParameter:parameter] animated:YES];

在構(gòu)造 NSMutableAttributedString 或者 NSAttributedString 設(shè)置的屬性值為 nil 導(dǎo)致閃退芥颈。

這個問題比較容易忽略,在實例化該對象是一定要小心赚抡、規(guī)范爬坑。

*** NSConcreteMutableAttributedString initWithString:: nil value

NSMutableAttributedString *attributedStr = [[NSMutableAttributedString alloc] initWithString: originStr];

NSInternalInconsistencyException:內(nèi)部不一致異常/內(nèi)部矛盾異常

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException',reason: 'Could not load NIB in bundle: 'NSBundle

NSArray*nib = [[NSBundle mainBundle] loadNibNamed:@"CellForOffers" owner:self options:nil];

loadNibNamed的xib不存在,出現(xiàn)NSInternalInconsistencyException錯誤

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException',reason: 'attempt to delete row 13 from section 0 which only contains 12 rows before the update'

- (void)insertRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;

- (void)deleteRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;

- (void)reloadRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation API_AVAILABLE(ios(3.0));

- (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath API_AVAILABLE(ios(5.0));

使用這4個方法要特別注意,它也數(shù)組一樣容易越界,屬于tableview的頁面row越界

Invalid update: invalid number of rows in section 0.The number of rows contained in an existing section after the update (2) must be equal to the number of rows contained in that section before the update (3),plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted)and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).

這種情況一般是數(shù)據(jù)源變化了,操作的時候和之前的數(shù)據(jù)源不一致了,一般出現(xiàn)在一些業(yè)務(wù)場景異步處理數(shù)據(jù)源.比如消息,網(wǎng)絡(luò)請求等

An instance 0x102471600 of class YYTextView was deallocated while key value observers were still registered with it. Current observation info:<NSKeyValueObservationInfo 0x174a20e60> ( <NSKeyValueObservance 0x174c59680: Observer: 0x174205ba0, Key path: contentSize, Options:?<New: YES, Old: YES, Prior: NO> Context: 0x0, Property: 0x174c59740> )

@weakify(self)

[self.textInputView.textView addObserverBlockForKeyPath:@"contentSize" block:^(YYTextView *obj, id _Nullable oldVal, id _Nullable newVal) {

? ????????@strongify(self)

? ? ? ? ? ?if (!self) return ;

}];


沒寫 [self.textInputView.textView removeObserverBlocks];ios11以下版本,會導(dǎo)致閃退

addObserverBlockForKeyPath卻忘記移除,當(dāng)這個類self回收了,再次觸發(fā)監(jiān)聽就會出現(xiàn)找不到改對象而出現(xiàn)閃退.類似的監(jiān)聽還有通知、KVO都會導(dǎo)致閃退.需要注意的下在ios11以下都會閃退,親測試ios11及以上不再會閃退,如果你的app需要兼容的系統(tǒng)版本是11及以上可以不需要寫,但是為了研發(fā)規(guī)范和習(xí)慣,建議都寫.

關(guān)于SIGSEGV

SIG 是信號名的通用前綴, SEGV 是 segmentation violation 的縮寫

在 POSIX 兼容的平臺上涂臣,SIGSEGV 是當(dāng)一個進(jìn)程執(zhí)行了一個無效的內(nèi)存引用盾计,或發(fā)生段錯誤時發(fā)送給它的信號。SIGSEGV 的符號常量在頭文件 signal.h 中定義赁遗。因為在不同平臺上,信號數(shù)字可能變化岩四,因此符號信號名被使用哭尝。通常剖煌,它是信號11。

閃退場景一:recorder deleteRecording 之前 先判斷文件是否存在耕姊,否則會造成過度釋放桶唐,解決方法:

if ([[NSFileManager defaultManager] fileExistsAtPath:self.recorder.url.path]) {

????if (![self.recorder deleteRecording])

????????????NSLog(@"Failed to delete %@", self.recorder.url);

}

閃退場景二: delegate = nil 。

將XXViewContrller設(shè)置為delegate時茉兰,當(dāng)頁面發(fā)生跳轉(zhuǎn)時尤泽,XXViewController的對象會被釋放,這是代碼走到[_delegate callbackMethod],便出現(xiàn)crash。解決方法有二:1.將@property (nonatomic ,assign) id <BLELibDelegate>delegate; 中 assign關(guān)鍵字改為weak安吁。 2.在XXViewController的delloc方法中添加:xxx.delegate = nil;

閃退場景三:鍵盤和使用了method swizzle將NSArray和NSMutableArray的objectAtIndex:等其他類進(jìn)行數(shù)據(jù)安全導(dǎo)致的

不管行為軌跡是如何的,在哪個頁面閃退,最后的本質(zhì)應(yīng)該都是一樣的.ios11以下版本,我們目前報過來的基本是10.3.3和少量的10.3.2、10.3.1 由于沒有真機,我們用模擬機模擬,如果不開啟Xcode的Zombie Objects,不是畢現(xiàn)的,很少機率偶發(fā)的.調(diào)試的時候可以開啟Xcode的Zombie Objects,并找到能彈出鍵盤的界面中燃辖,鍵盤顯示的情況下 home app 進(jìn)入后臺鬼店,再單擊app 圖標(biāo) 切換回前臺時 發(fā)生crash.

處理:Safe文件設(shè)置為掛鉤NSMutableArray方法編譯器標(biāo)志的位置 -fno-objc-arc 或者不使用方法交換的方式來做safe處理.

Methodmethod = class_getInstanceMethod(NSClassFromString(@"__NSArrayM"),@selector(objectAtIndex:));Method method2 = class_getInstanceMethod(NSClassFromString(@"__NSArrayM"),?@selector(safeObjectAtIndex:));method_exchangeImplementations(method, method2);

去調(diào)類似代碼,讓開發(fā)人員規(guī)范開發(fā)不依賴safe類.

好了就寫到這里了,這就是我們項目中發(fā)現(xiàn)的一些問題,后面有新的問題再來補充,或大家有啥發(fā)現(xiàn)也可以來補充.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市黔龟,隨后出現(xiàn)的幾起案子妇智,更是在濱河造成了極大的恐慌,老刑警劉巖氏身,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件巍棱,死亡現(xiàn)場離奇詭異,居然都是意外死亡蛋欣,警方通過查閱死者的電腦和手機航徙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來陷虎,“玉大人到踏,你說我怎么就攤上這事∥迅澹” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵伴榔,是天一觀的道長庄萎。 經(jīng)常有香客問我踪少,道長,這世上最難降的妖魔是什么糠涛? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮脱羡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘锉罐。我一直安慰自己帆竹,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布脓规。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪绢陌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天脐湾,我揣著相機與錄音叙淌,去河邊找鬼。 笑死鹰霍,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的孟岛。 我是一名探鬼主播督勺,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼堵未!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起渗蟹,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤赞辩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后世落,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體糟需,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡屉佳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年武花,在試婚紗的時候發(fā)現(xiàn)自己被綠了杈帐。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片专钉。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡累铅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出娃兽,到底是詐尸還是另有隱情,我是刑警寧澤玉雾,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布轻要,位于F島的核電站垦缅,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏壁涎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一嚼酝、第九天 我趴在偏房一處隱蔽的房頂上張望竟坛。 院中可真熱鬧缸匪,春花似錦、人聲如沸宣虾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至审编,卻和暖如春歧匈,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工矮湘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留口糕,地道東北人。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓十办,卻偏偏與公主長得像,于是被迫代替她去往敵國和親向族。 傳聞我的和親對象是個殘疾皇子棠绘,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,611評論 2 353

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