異常處理NSException的使用(思惟篇)

關於異常處理的使用的格式基本就是:程序員

@try {

} @catch (NSException *exception) {

} @finally {

}

經過這段時間對異常處理相關知識的整理,我以爲須要掌握如下幾個方面的內容:數組

1 要會建立NSException對象,而且會使用@throw拋出異常安全

2 瞭解異常處理的做用服務器

 

使用@try進行異常處理,一開始會有相似下面兩個問題弄不明白:app

1 既然異常發生了,程序必定會退出,那還須要@final邏輯幹嗎,程序退出了一切都從新開始不就好了框架

2 異常發生後,而後判斷是屬於哪一種異常,使用@catch分別處理的意圖是什麼呢優化

 

舉個簡單的例子,對數組越界訪問(好比數組總共3個元素,取第4個元素就會產生異常)spa

- (void)test {
    NSString *name = [self queryValue];
    NSLog(@">>>>>>>>>%@", name);
    if (!name) {
        NSLog(@">>>>>>>>>通知服務器取值失敗");
    } else {
        NSLog(@">>>>>>>>>通知服務器取值成功");
    }
}

- (NSString *)queryValue {
    NSArray *arr = @[@"111", @"222", @"333"];
    NSString *string = [arr objectAtIndex:3];
    return string;
}

控制檯打印的信息:code

2021-08-08 23:35:12.956564+0800 OCTestLine[22690:1921426] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** __boundsFail: index 3 beyond bounds [0 .. 2]'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff2dd5ff53 __exceptionPreprocess + 250
    1   libobjc.A.dylib                     0x00007fff63e25835 objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff2de22d3a _CFThrowFormattedException + 202
    3   CoreFoundation                      0x00007fff2de2a203 -[__NSArrayI getObjects:range:].cold.1 + 0
    4   CoreFoundation                      0x00007fff2dcbd061 -[__NSSingleObjectSetI member:] + 0
    5   OCTestLine                          0x0000000100000d97 -[PersonClass queryValue] + 135
    6   OCTestLine                          0x0000000100000c9c -[PersonClass test] + 44
    7   OCTestLine                          0x0000000100000c47 main + 87
    8   libdyld.dylib                       0x00007fff651882e5 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

關於這種越界取值的狀況,程序會直接拋出異常,拋出異常的結果就是程序crash(崩潰),這在程序開發過程當中相對於「錯誤」,「異常」致使crash更容易定位bug,這樣直截了當地crash的確也沒什麼,定位bug、修改代碼、從新運行就好了,所以在軟件開發過程當中,「異常處理」的確沒什麼用。可是若是有如下需求呢?orm

1 程序閃退以前,我想把這個「異常」信息記錄下來,或者記錄在本地,或者上傳記錄在服務器上,方便後期修復優化代碼;

2 程序閃退以前,我想把一些「操做」作完,以確保整個系統的安全性;

這樣的需求並不過度,好比用戶下載了已經發布的版本,使用過程當中出現了閃退,確定是須要進行crash統計的,方便程序員定位問題,騰訊Bugly就是基於此需求開發的框架。

另外,使用異常處理有個現實狀況是,當App出現異常閃退了,可是並無真正的「殺死」進程,這個時候是能夠繼續使用該App的進程繼續作其餘操做的(好比上傳異常信息到服務器)。

{
    NSString *name;
}

- (void)test {
    @try {
        name = [self queryValue];
        NSLog(@">>>>>>>>>%@", name);
    } @catch (NSException *exception) {
        NSLog(@">>>>>>>>>%@", exception);
        for (int i = 1; i < 11; i++) {
            sleep(1);
            NSLog(@">>>>>>>>>將錯誤信息上傳服務器進度:%d%%", i*10);
        }
    } @finally {
        for (int i = 10; i > 0; i--) {
            sleep(1);
            NSLog(@">>>>>>>>>退出程序倒計時:%d", i);
        }
        if (!name) {
            NSLog(@">>>>>>>>>通知服務器取值失敗");
        } else {
            NSLog(@">>>>>>>>>通知服務器取值成功");
        }
    }
}

- (NSString *)queryValue {
    NSArray *arr = @[@"111", @"222", @"333"];
    NSString *string = [arr objectAtIndex:3];
    return string;
}

在控制檯的打印結果以下:

2021-08-09 00:00:47.686273+0800 OCTestLine[22920:1933899] >>>>>>>>>*** __boundsFail: index 3 beyond bounds [0 .. 2]
2021-08-09 00:00:48.688200+0800 OCTestLine[22920:1933899] >>>>>>>>>將錯誤信息上傳服務器進度:10%
2021-08-09 00:00:49.693500+0800 OCTestLine[22920:1933899] >>>>>>>>>將錯誤信息上傳服務器進度:20%
2021-08-09 00:00:50.698861+0800 OCTestLine[22920:1933899] >>>>>>>>>將錯誤信息上傳服務器進度:30%
2021-08-09 00:00:51.704219+0800 OCTestLine[22920:1933899] >>>>>>>>>將錯誤信息上傳服務器進度:40%
2021-08-09 00:00:52.709532+0800 OCTestLine[22920:1933899] >>>>>>>>>將錯誤信息上傳服務器進度:50%
2021-08-09 00:00:53.714876+0800 OCTestLine[22920:1933899] >>>>>>>>>將錯誤信息上傳服務器進度:60%
2021-08-09 00:00:54.720185+0800 OCTestLine[22920:1933899] >>>>>>>>>將錯誤信息上傳服務器進度:70%
2021-08-09 00:00:55.725510+0800 OCTestLine[22920:1933899] >>>>>>>>>將錯誤信息上傳服務器進度:80%
2021-08-09 00:00:56.726721+0800 OCTestLine[22920:1933899] >>>>>>>>>將錯誤信息上傳服務器進度:90%
2021-08-09 00:00:57.732028+0800 OCTestLine[22920:1933899] >>>>>>>>>將錯誤信息上傳服務器進度:100%
2021-08-09 00:00:58.737385+0800 OCTestLine[22920:1933899] >>>>>>>>>退出程序倒計時:10
2021-08-09 00:00:59.741825+0800 OCTestLine[22920:1933899] >>>>>>>>>退出程序倒計時:9
2021-08-09 00:01:00.747129+0800 OCTestLine[22920:1933899] >>>>>>>>>退出程序倒計時:8
2021-08-09 00:01:01.752443+0800 OCTestLine[22920:1933899] >>>>>>>>>退出程序倒計時:7
2021-08-09 00:01:02.757756+0800 OCTestLine[22920:1933899] >>>>>>>>>退出程序倒計時:6
2021-08-09 00:01:03.763067+0800 OCTestLine[22920:1933899] >>>>>>>>>退出程序倒計時:5
2021-08-09 00:01:04.768387+0800 OCTestLine[22920:1933899] >>>>>>>>>退出程序倒計時:4
2021-08-09 00:01:05.773704+0800 OCTestLine[22920:1933899] >>>>>>>>>退出程序倒計時:3
2021-08-09 00:01:06.774743+0800 OCTestLine[22920:1933899] >>>>>>>>>退出程序倒計時:2
2021-08-09 00:01:07.780073+0800 OCTestLine[22920:1933899] >>>>>>>>>退出程序倒計時:1
2021-08-09 00:01:07.780251+0800 OCTestLine[22920:1933899] >>>>>>>>>通知服務器取值失敗
Program ended with exit code: 0

關於控制檯打印的信息,有兩點說明:

1 仔細看打印的時間,能夠知道,異常發生後,app閃退後,後臺進程並無退出,在用戶經過「多任務」進行刪除app以前,依然能夠運行代碼作不少事;

2 使用@try正常處理異常,程序是屬於正常退出的,「Program ended with exit code:0」。

相關文章
相關標籤/搜索