2011-02-15 123 views
78

在Cocoa中,我應該何時使用NSAssert,NSException,NSError?Objective-C:聲明與異常與錯誤

這就是我一直在想:

NSAssert - 當創建用於程序員自己的利益來仔細檢查規則,慣例,假設或前提條件和後置條件的任何客戶端程序?

NSException - 當爲使用該庫的其他程序員的利益創建第三方庫時,以便他們立即知道輸入何時失效?

NSError - 當與外部系統連接以獲取不保證給我結果的文件,數據庫或Web服務等數據時?

回答

98

NSAssert將失敗時會引發異常。因此,NSAssert可以簡單易用地編寫代碼並檢查您在代碼中所做的任何假設。這不是(在我看來)是例外的替代方案,只是一種捷徑。如果一個斷言失敗了,那麼代碼中的某些事情就會發生嚴重錯誤,程序不應該繼續。

有一點需要注意的是,NSAssert不會被編譯到您的代碼發佈版本,所以這通常用於在開發過程中進行完整性檢查。我實際上傾向於使用始終處於活動狀態的自定義斷言宏。

你會@throw自己NSException的時間是指當你肯定希望它在發佈版本,並在東西像公共圖書館/接口時,一些參數是無效的,或者你已經被稱爲不正確。請注意,@catch例外並不是真正的標準做法,並且繼續運行您的應用程序。如果您嘗試使用Apple的某些標準庫(例如Core Data),可能會發生不良事情。與斷言類似,如果拋出異常,應用程序通常應該相當快地終止,因爲這意味着某處存在編程錯誤。

NSErrors應該在您的庫/接口中用於非編程錯誤並且可以從中恢復的錯誤。您可以向調用者提供信息/錯誤代碼,他們可以乾淨地處理錯誤,在適當的時候提醒用戶,並繼續執行。這通常適用於文件未找到錯誤或其他非致命錯誤。

1

一般而言,異常用於表示程序員錯誤 - 它們是不應該發生的事情。錯誤用於表示程序正常運行時可能出現的錯誤情況 - 基本上是用戶錯誤,或者需要是真的但可能不是的外部情況。所以試圖刪除文檔中的某個鎖定元素可能是一個錯誤,並且試圖在沒有Internet連接的情況下下載文件將是一個錯誤,但嘗試訪問集合中的無效元素將是一個例外。

斷言通常用於測試,並且AFAIK不會像其他錯誤處理機制一樣用作通用錯誤處理機制。

+0

斷言可以用來執行不變量。例如,`NSParameterAssert(someParam!= nil);`將強制指定參數不能爲零的不變量。 – 2011-02-15 21:29:20

+0

@Kevin Ballard:斷言通常是由發佈版本定義的,或者至少它們是我最後一次檢查的,所以就像我說的那樣,它們不是一般的錯誤處理機制。 – Chuck 2011-02-15 22:32:04

3

Cocoa中的約定是,異常表示程序員錯誤。很多代碼,包括框架代碼,都不能在拋出異常後正常工作。

任何應該可恢復的錯誤都由NSError表示。還有一個向用戶呈現NSError的系統。正如你所說,這對於易出故障的外部資源是非常有用的。

從概念上講,斷言是給定謂詞總是評估爲真的陳述;如果沒有,該程序被破壞。雖然其行爲可以修改,但NSAssert系列默認是一種方便的方式來投擲NSInternalInconsistencyException(可以在發佈版本中將其關閉)。

2

編輯: 在Xcode中4.2,assertions are turned off by default for release builds,

現在NSAssert不會被編譯成一個釋放你的代碼構建,但你可以在構建設置更改


@Mike韋勒,你的答案有一個錯誤。

有一點要注意的是,NSAssert不會被編譯成一個發佈版本你的代碼,所以這通常用於開發過程中健全檢查。

其實,NSAssert會被編譯成代碼如果你沒有在你的預編譯前綴文件添加NS_BLOCK_ASSERTIONS

在技術說明TN2190我們可以發現:

宏像NDEBUG轉關C斷言或NS_BLOCK_ASSERTIONS關閉基金會的NSAssert是很重要的指定預編譯前綴文件

或者你可以讀取這一個:How to know if NSAssert is disabled in release builds?