http://www.devbean.info/2011/04/from_cpp_to_objc_17/
異常處理
比起 C++ 來,Objective-C 中的異常處理更像 Java,這主要是因為 Objective-C 有一個 @finally 關鍵字。Java 中也有一個類似的 finally 關鍵字,但 C++ 中則沒有。finally 是 try()…catch() 塊的一個可選附加塊,其中的代碼是必須執行的,不管有沒有捕獲到異常。這種設計可以很方便地寫出簡短乾淨的代碼,比如資源釋放等。除此之外,Objective-C 中的 @try…@catch…@finally 是很經典的設計,同大多數語言沒有什麼區別。但是,不同於 C++ 的還有一點,Objective-C 只有對象可以被拋除。
不帶 finally |
帶有 finally |
BOOL problem = YES;@try { dangerousAction(); problem = NO;} @catch (MyException* e) { doSomething(); cleanup();} @catch (NSException* e) { doSomethingElse(); cleanup(); // 重新拋出異常 @throw}if (!problem) cleanup(); |
@try { dangerousAction();} @catch (MyException* e) { doSomething();} @catch (NSException* e) { doSomethingElse(); @throw // 重新拋出異常} @finally { cleanup();} |
嚴格說來,@finally 不是必要的,但是確實是處理異常強有力的工具。正如前面的例子所示,我們也可以在 @catch 中將異常重新拋出。事實上,@finally 在 @try 塊運行結束之後才會執行。對此我們將在下面進行解釋。
int f(void){ printf("f: 1-you see me\n"); // 注意看輸出的字串,體會異常處理流程 @throw [NSException exceptionWithName:@"panic" reason:@"you don’t really want to known" userInfo:nil]; printf("f: 2-you never see me\n");} int g(void){ printf("g: 1-you see me\n"); @try { f(); printf("g: 2-you do not see me (in this example)\n"); } @catch(NSException* e) { printf("g: 3-you see me\n"); @throw; printf("g: 4-you never see me\n"); } @finally { printf("g: 5-you see me\n"); } printf("g: 6-you do not see me (in this example)\n");}
最後一點,C++ 的 catch(…) 可以捕獲任意值,但是 Objective-C 中是不可以的。事實上,只有對象可以被拋出,也就是說,我們可以始終使用 id 捕獲異常。
另外注意,Cocoa 中有一個 NSException 類,推薦使用此類作為一切異常類的父類。因此,catch(NSException *e) 相當於 C++ 的 catch(…)。
多線程
安全執行緒
在Objective-C 中可以很清晰地使用 POSIX APIs 2 實現多線程。Cocoa 提供了自己的類管理多線程。有一點是需要注意的:多個線程同時訪問同一個記憶體地區時,可能會導致不可預料的結果。POSIX APIs 和 Cocoa 都提供了鎖和互斥對象。Objective-C 提供了一個關鍵字 @synchronized,與 Java 的同名關鍵字是一樣的。
@synchronized
由 @synchronized(…) 包圍的塊會自動加鎖,保證一次只有一個線程使用。在處理並發時,這並不是最好的解決方案,但卻是對大多數關鍵塊的最簡單、最輕量、最方便的解決方案。@synchonized 要求使用一個對象作為參數(可以是任何對象,比如 self),將這個對象作為鎖使用。
@implementation MyClass -(void) criticalMethod:(id) anObject { @synchronized(self) { // 這段代碼對其他 @synchronized(self) 都是互斥的 // self 是同一個對象 } @synchronized(anObject) { // 這段代碼對其他 @synchronized(anObject) 都是互斥的 // anObject 是同一個對象 }}@end