1

提前,請原諒我對iPhone/Objective-C最佳實踐缺乏理解;我來自.NET/C#背景。iPhone生產/發佈異常處理

儘管我已經閱讀了許多關於iPhone異常處理的文章,但我仍然不完全清楚大多數人爲生產代碼所做的工作。此外,我還沒有找到任何開放源碼的應用程序,我通常會期望錯誤處理。這裏是我的問題:

1)如果意外的結果發生會導致應用程序最終失敗,你會拋出一個異常或只是等待它失敗以後?例如,

if (![fileManager createDirectoryAtPath: myNewDir 
    withIntermediateDirectories: YES 
    attributes: nil 
    error: &myError]) { 

    // My app shouldn't continue. Should I raise an exception? 
    // Or should I just log it and then wait for it to crash later? 
} 

2)您是否驗證參數?例如,在C#中,我通常會檢查null,如果需要的話拋出一個ArgumentNullException。

3)當應用程序崩潰時,崩潰信息會自動記錄,還是需要設置未處理的異常處理程序?我可以在此方法中顯示UIAlertView以通知用戶發生了什麼不愉快的事情,而不是讓應用程序消失嗎? (如果是這樣,我不能得到它的工作。)

4)最後,爲什麼我沒有看到任何人最終使用@ try/@ catch/@?它在C#中廣泛使用,但我還沒有找到使用它的開源應用程序。 (也許我只是看着錯誤的應用程序。)

回答

2

Ad 1.您給出的例子是一個有點經典的例子,當時應該在Java中使用「checked異常」。該方法的調用者必須準備好,該調用可能因爲可以控制的原因而失敗。特別是,在給出的示例中,我將允許錯誤描述對象允許傳播給調用者:

- (BOOL) prepareDirectories: (NSString*) path error: (NSError**) location { 

    if(![fileManager createDirectoryAtPath: path 
         withIntermediateDirectories: YES 
         attributes: nil 
         error: location]) { 

     return NO; 
    } 

    // ... additional set-up here 
    return YES; 
} 

如果錯誤真的是不可恢復的,你實際上可能引發異常,但也將被沒收任何機會向您的應用程序的用戶顯示適當的錯誤消息。

廣告2.是的,參數確認絕對是您應該做的。並提出意想不到的nil的例外是完全合適的。一個錯誤的參數是「程序員的錯誤」,你不能保證程序仍然處於一致的狀態。例如,如果嘗試使用不存在的索引獲取元素,NSArray會引發異常。

廣告3.當應用程序由於未捕獲的異常而崩潰時,事實會自動記錄。如果您確實想要顯示錯誤消息,則可以捕獲該異常。但是,該應用可能處於不一致的狀態,並且不應該被允許繼續,所以簡單地允許它停下來似乎是最好的解決方案。

廣告4.我不知道。

1
  1. 在您提到的具體情況下,您應該向用戶提供有關如何解決情況的說明剛剛發生的通知。除非在極端情況下你的應用程序不應該退出。你應該讓用戶解決任何錯誤,然後再試一次。
  2. 參數驗證取決於很多因素。有一點需要記住的是,在Obj-C中,發送消息到nil是完全有效的(如果你這樣做,沒有任何反應),所以在很多情況下你不需要檢查零。如果我在模型類中,我總是在方法中驗證參數。如果我不是,我幾乎從不驗證任何東西,類型檢查就足夠了。
  3. 應記錄一些信息,但記錄更多具體信息對您的情況總是有幫助的。理想情況下,您不應該達到未處理的異常狀態。
  4. 可可類很少會因爲環境原因拋出異常,它們幾乎總是因爲你做錯了什麼。例如,你通常不會在[NSString stringWithString:]周圍放置一個@ try/@ catch塊,因爲它會拋出異常的唯一方式是如果你嘗試並通過nil。確保你沒有通過nil,你不必擔心捕捉異常。當一個方法可能因爲你不能控制的東西而失敗時,它們通常通過NSError進行通信。例如,請參閱- (BOOL)save:(NSError **)error方法NSManagedObjectContext