建議大型項目用上Try Catch

建議大型項目用上Try Catch

我們在平時項目做功能的時候,經常會遇到崩潰的情況。如果是我們在開發測試階段,我們可以找到原因修復。但是遇到已經上線,出現這種問題。要么使用JSPatch進行熱修復,但是使用熱修復修復苦只有寫的人知道。

本來就是一個方法一個單詞寫錯,一個值沒做異常處理,就要重寫整個方法。對于像我這樣根本不懂JS語法和不精通JSPatch的人來說,真的是藍瘦,香菇。

最近寫的項目用Swift語法進行編寫的,對于之前我們在Object-CNSError**類型的指針標識遇到了什么錯誤,現在轉成Swift方法直接進行throws進行拋異常。

這樣我們就必須使用Do Catch進行捕獲異常了,我覺得蘋果這樣做真的挺好的。

比如我剛剛寫的項目,就用上了,感覺用完頓時高大上了許多。

import Cocoa

enum OFileMagerImportError:Error {
  case cannel //點擊了取消的按鈕
  case error(message:String)
}

class OFileManger: NSObject {
  /*
   * 導入配置文件
   * return 返回一個數組對象 可能返回為空
   */
  class func importAction() throws -> [Any] {
      let openPannel = NSOpenPanel()
      openPannel.allowedFileTypes = ["ork"]; // 只允許讀取.ork的文件類型
      openPannel.allowsMultipleSelection = false // 設置不允許多選
      let buttonIndex = openPannel.runModal()
      guard buttonIndex == NSFileHandlingPanelOKButton else {
          throw OFileMagerImportError.cannel
      }
      guard openPannel.urls.count > 0 else {
          throw OFileMagerImportError.error(message:"你還沒有選擇任何的配置文件!")
      }
      guard let fileName = openPannel.urls.first else {
          throw OFileMagerImportError.error(message:"你還沒有選擇任何的配置文件!")
      }
      guard let jsonData = try? Data(contentsOf: fileName) else {
          throw OFileMagerImportError.error(message:"讀取文件內容失敗!")
      }
      guard let jsonObj = try? JSONSerialization.jsonObject(with: jsonData, options: .allowFragments) else {
          throw OFileMagerImportError.error(message:"配置文件內容不是一個JSON文本!")
      }
      guard let configList:[Any] = jsonObj as? [Any] else {
          throw OFileMagerImportError.error(message:"配置文件內容不是一個數組對象!")
      }
      return configList
  }


}

調用的時候我們可以這么寫。

@IBAction func importAction(_ sender: Any) {
        do {
            let configList:[Any] = try OFileManger.importAction()
            print(configList)
        } catch OFileMagerImportError.error(let message) {
            OAlertMessage.alert(message: message)
        } catch {
            print("拋出了其他不給用戶看到的錯誤!")
        }
    }

我們就可以做一些錯誤的處理。但是只是這樣,我心里面還不是十分強烈想用。

后來線上的App在雙11那天晚上突然出現打不開崩潰的情況,在外面準備吃飯慶祝的強行喊回去解決問題。

回去覺得應該是那里崩潰了吧,應該也是十分的容易解決。

后來發現因為接口因為最近上線的功能出問題了,就回滾了代碼。導致之前一些接口的字段沒有返回,恰好那個接口沒有用Model進行映射,所以就出現崩潰了。

經理一直問這個接口回滾好幾天了為啥突然出問題了,原來是接口做了緩存,會根據后臺返回是否需要更新才會重新的請求接口。

雙11那天正好運維更新了數據,導致接口重新請求,少了字段導致崩潰。最后讓后臺強行把拿兩個字段返回,最快的解決問題。

雖然讓后臺加上了字段,但是我覺得我們App這里沒有做好兼容,才導致這一次事故。幸虧沒影響多久,再說客戶都是外國人,那個時間還沒睡醒。

我們平時遇到的一些崩潰問題所在

  • 數組越界
  • 給一個可變數組強行賦值不可變,之后當做可變數組用
  • 字典值不存在
  • 后臺返回的字段不統一,本來有值是字典,沒值是字符串。

導致的崩潰自然不止這些,但是這些占據了崩潰里面大部分,前三個我們可以做一下異常處理,最后一個最好還是讓后臺規范起來,這是長遠之際。或者使用Model進行映射。

怎么做異常處理

  • 做很多if else判斷
  • 使用Try catch進行處理

雖然兩個都要寫很多的代碼,if else的代碼更加優美一點,但是就怕有一種情況你沒寫出來。覺得最好的辦法還是用try catch進行。

@try@catch@throw,和 @finally。這四個關鍵詞進行異常處理。

我們看一下常見的一個數組越界的例子:

NSArray *tests = @[];
NSNumber *num = tests[0];

我們不用運行就可以知道這個地方會崩潰,因為我們初始化的數組是空的。但是我們強行取一個元素,導致崩潰。

假設我們現在用上了try catch的代碼,會如何呢。

NSArray *tests = @[];
@try {
    NSNumber *num = tests[0];
} @catch (NSException *exception) {
    NSLog(@"%@",exception.userInfo);
} @finally {
    NSLog(@"我做一些必須的處理");
}

經過測試,這個代碼會在Debug的時候斷點,但是強行運行還是可以運行的。但是在Release發布之后運行完全沒有任何的影響。

雖然我們平時寫代碼上面,不可能讓所有出現異常的地方寫上這樣的代碼。但是對著我們的經驗,我們對于一眼就知道會出崩潰的地方加上,還是能讓線上的應用少出很多問題的。

關于Try catch的資料可以查看下面資料:

iOS捕獲異常,常用的異常處理方法

Swift中錯誤和異常處理

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,778評論 18 399
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,556評論 25 708
  • 集合框架: 1)特點:存儲對象;長度可變;存儲對象的類型可不同2)Collection(1)List:有序的;元素...
    Demo_Yang閱讀 1,286評論 0 4
  • (曼谷情) 文/菊 佛地硝煙彌曼谷, 祥云吐瑞醉游仙, 晨輝碧照琉金塔, 溢彩奇光艷照天。 【平水韻】一先 (乙未...
    斌之志閱讀 655評論 2 6
  • 每當一個案件在審理過程中,做為律師最為糾結的是等待自己所期待的結果,但該期待又是多么的令人心神不寧。唉!糾結是訴訟...
    aead799f9258閱讀 164評論 0 0