我的一位朋友問我不要在iPhone應用程序中使用NSException。他給出的原因是「性能瓶頸」。但我不相信它。在iPhone應用程序中使用NSException
有人可以確認我們應該禁止在iPhone應用程序中使用NSException嗎?如果您有使用NSException的最佳實踐,請提供。
UPDATE:
這link要求我們在應用級使用異常處理。有人曾經做過嗎?請說明它的優點以及它可能產生的其他任何表現。
我的一位朋友問我不要在iPhone應用程序中使用NSException。他給出的原因是「性能瓶頸」。但我不相信它。在iPhone應用程序中使用NSException
有人可以確認我們應該禁止在iPhone應用程序中使用NSException嗎?如果您有使用NSException的最佳實踐,請提供。
UPDATE:
這link要求我們在應用級使用異常處理。有人曾經做過嗎?請說明它的優點以及它可能產生的其他任何表現。
簡而言之:
只有適合使用@嘗試/ @趕上來處理不可恢復的錯誤。使用@ throw/@ try/@ catch在iOS或Mac OS X上執行類似操作的控制流是絕對不合適的。即便如此,請仔細考慮是否最好使用異常來指示不可恢復的錯誤或僅僅是崩潰(調用abort());事故經常會留下更多的證據。
例如,除非您的目標是捕捉它們並以某種方式報告錯誤,否則 - 通常 - 崩潰或至少警告該錯誤,否則它不適合用於捕獲越界異常用戶表示您的應用處於不一致狀態,並可能會丟失數據。
通過系統框架代碼拋出的任何異常的行爲是未定義的。
你能解釋一下「通過系統 框架代碼是未定義的拋出的任何異常 行爲。」在 的詳細資料?
當然。
系統框架使用一種設計,其中任何異常被認爲是致命的,不可恢復的錯誤;一個程序員錯誤,爲所有意圖和目的。這條規則的例外(heh)數量非常有限。
因此,在它們的實現中,如果通過系統框架代碼拋出異常,系統框架將不能確保一切都必須正確地清理乾淨。根據定義,正常情況下,例外是不可恢復的,爲什麼要支付清理費用?
考慮這個調用堆棧:
your-code-1()
system-code()
your-code-2()
即代碼將代碼調用到調用更多代碼的系統代碼中(一種非常常見的模式,儘管調用堆棧明顯更深)。
如果your-code-2
引發異常,異常通過system-code
表示行爲未定義; system-code
可能會或可能不會讓您的應用程序處於未定義的,潛在的崩潰或數據有損狀態。
或者更爲強烈:您不能在your-code-2
中拋出異常,期望您可以在your-code-1
中捕捉並處理它。
我使用異常處理我相當密集的audio app沒有任何問題。經過多次閱讀和一些基準測試和反彙編分析後,我發現了一個有爭議的結論:沒有真正的理由不使用它們(智能地)並且沒有足夠的理由(NSError指針指針,無盡條件...呸!)。大多數人在論壇上發表的意見都是重複Apple Docs。
我去到相當多的細節,在this blog post,但我會在這裏勾勒出我的發現:
在我的iPhone 4上,拋出和捕捉100萬個異常大約需要8.5秒。這相當於每個只有大約8.5微秒。在實時CoreAudio線程中價格昂貴?也許有點(但你永遠不會拋出異常嗎?),但UIAlert的8.5μs延遲告訴用戶打開文件時出現問題,是否會被注意到?
蘋果的文檔「上零成本@try塊」和國家的說出32位招致成本。小小的基準測試和反彙編分析似乎表明,在32位iOS(ARM處理器)上也有零成本的@try塊。蘋果的意思是說32bit 英特爾?
是的,他們是「不確定」,但你在幹什麼通過蘋果框架扔呢? 當然蘋果不會爲你處理它們。 實現可恢復錯誤異常處理的重點是在本地處理它們,而不是在本地「單線」處理。
這裏的一個邊緣案例是與像NSObject:performSelectorOnMainThread:waitUntilDone:
一樣的方法。如果後面的參數是YES,這就像是一個同步函數,在這種情況下,您可能會被原諒,因爲期望異常會向您的調用範圍發送。例如:
/////////////////////////////////////////////////////////////////////////
#pragma mark - l5CCThread
/////////////////////////////////////////////////////////////////////////
@interface l5CCThread : NSThread @end
@implementation l5CCThread
- (void)main
{
@try {
[self performSelectorOnMainThread:@selector(_throwsAnException) withObject:nil waitUntilDone:YES];
} @catch (NSException *e) {
NSLog(@"Exception caught!");
}
}
- (void)_throwsAnException { @throw [NSException exceptionWithName:@"Exception" reason:@"" userInfo:nil]; }
@end
/////////////////////////////////////////////////////////////////////////
#pragma mark - l5CCAppDelegate
/////////////////////////////////////////////////////////////////////////
@implementation l5CCAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
l5CCThread *thd = [[l5CCThread alloc] init];
[thd start];
return YES;
}
// ...
在這種情況下,除了將通過「通過Cocoa框架」(主線程的run loop)缺少你捕捉和崩潰。您可以使用GCD的dispatch_synch
輕鬆解決此問題,並將方法調用加上其塊參數加上任何異常處理。
任何人都知道什麼是苦差事它是檢查,處理和報告錯誤。 @ try/@ catch和NSExceptions提供的主要好處是讓你的代碼更簡潔,更易於維護。
假設你有5行代碼在文件上工作。每個可能會拋出一個,比如3個不同的錯誤(例如,磁盤空間不足,讀取錯誤等)。不是將每行都包含在檢查NO返回值的條件中,而是將NSError指針調查外包給另一個ObjC方法(或者更糟糕的是,使用的宏是#define
!),則將所有5行全部包含在 @try中,並將其包裝爲 @try在那裏處理每個錯誤。想想你會省下的路線!
通過創建NSException子類,您還可以輕鬆集中錯誤消息,並避免您的代碼與他們散落在一起。您還可以輕鬆區分應用程序的「非致命」異常與致命程序員錯誤(如NSAssert)。您也可以避免使用「name」常量(子類的名稱,即「名稱」)。關於基準和拆卸的這一切
例子和更多的細節是on this blog post ...
例外加的try/catch /最後是(C++,Java,PHP和通過幾乎使用所有其他主要語言範式, Ruby,Python)。也許是時候放棄這種偏執狂了,至少在iOS中也是如此。
你能解釋一下:「通過系統框架代碼拋出的任何異常的行爲是未定義的。」詳細? – Krishnan 2010-11-30 08:35:54