【小(xiǎo)編推薦】不(bù)算(suàn)“真正的(γ$÷£de)語言”?詳說(shuō)Swift 2.0中的(de)錯(c≤•☆>uò)誤處理(lǐ)

2015-07-02   |&nbsδ≤p;  發布者:梁國(g≤™>≥uó)芳   |&nbs₩≥<γp;  查看(kàn):3320次

IT新聞
 蘋果公司在今年(nián)的(de)全球開(kāi)發者∏₹∑<大(dà)會(huì)(Worldwide Developers≥≈£ Conference, WWDC)上(shàng)宣布推出Swift2.0, ↕該語言的(de)首席架構師(shī)Chris Lattner€ ♦₹表示,Swift 2.0主要(yào)在語言基本語法、安全性和(hé)格×¶式美(měi)觀度這(zhè)三方面進行(xíng)了'σ↔(le)改進。除了(le)這(zhè)些(xi÷​←§ē)新的(de)功能(néng)特性,還(•≈≈​hái)有(yǒu)對(duì)語法的(de)優化(huà)、修飾及美(měi↔∑ )化(huà),最後是(shì)Swift 1.x中最具影(yǐ♣ ₩×ng)響力的(de)錯(cuò)誤處理(lǐ)機(jī)制(zhì)→γ。

這(zhè)是(shì)因為(wèi)你(nǐ)∞∞根本無法回避它。如(rú)果打算(suàn)使用(yòng)Swift$≤≈✔ 2.0的(de)話(huà),必須接受錯(cuò)誤處理(lǐ≤✔¶)這(zhè)樣的(de)機(jī)制(zhì),并且錯(cuò)誤™σ←處理(lǐ)機(jī)制(zhì)将改變Cocoa和(hé)Cocoa®σ₹ Touch框架中使用(yòng)NSError與方法交互的(de)方式。λ₽γ

曆史一(yī)瞬:不(bù)起眼的(de)開(kāi)端

我們都(dōu)知(zhī)道(dào),Swift語言作(zuò)為(wèi♠γ♣)Objective-C當前替代語言被推出,是(shì)OS X和(hé)i≤™$¶OS應用(yòng)程序開(kāi)發的(&§×de)“通(tōng)用(yòng)語”。在最初的(de)版本中,Objective-C沒有(§λyǒu)原生(shēng)的(de)異常處理→®γ(lǐ)機(jī)制(zhì)。後來(lái)₩≥©ε通(tōng)過添加NSException類,還(hái)有(yǒu) N§∑§S_DURING, NS_HANDLER和(h≥→α‍é) NS_ENDHANDLER宏才有(yǒu)了(le)異常處γπ 理(lǐ)。這(zhè)種方案現(xiàn)在被稱為(w∞↕èi)“經典的(de)異常處理(lǐ)&rdq ​←®uo;,還(hái)有(yǒu)這(zhè)些(xiē)宏都(dōu)是(ε→shì)基于setjmp()和(hé)longjmp()這(zhè)"‌≈₹兩個(gè)C語言函數(shù)的(de•"♣α)。

異常捕獲(exception-catchiβ©₹☆ng)看(kàn)起來(lái)如(rú)下(xià)所示,在NS_DURIN ♦₩G和(hé)NS_HANDLER宏之間(jiān)×✔抛出的(de)任何異常都(dōu)将會(huì)導緻在NS_HANDLER和(¥∑hé)NS_ENDHANDLER宏之間(jiān)執行(xíng)相(♥≈∑ xiàng)應的(de)代碼。

 

[cpp] view plaincopy
 
  1. NS_DURING  
  2.     // Call a&nb✘&÷sp;dangerous method&¶≠π↔nbsp;or functio♠™★n that raise₹♠∞®s an exception:  
  3.     [obj som≠γeRiskyMethod];  
  4. NS_HANDLER  
  5.     NSLog≠β¥(@"Oh no!&quo✔‍t;);  
  6.     [anot★ δ≈herObj makeItRigΩε£ht];  
  7. NS_ENDHANDLER  

 

下(xià)面是(shì)立刻能(néng§€λ©)觸發抛出異常的(de)方法(現(xiàn)在仍$&然可(kě)用(yòng)):

 

[cpp] view plaincopy
 
  1. - (void)someRiskyMethod  
  2. {  
  3.     [NSExcept↑₹ion raise:@"Kablam"  
  4.     &nbs‌↑♣¥p;    &n★∞≠bsp;     &n​₩✘bsp;format:@"This meth±πε♠od is not >₹₩≠implemented yet. Doπ×♣σ not call!"];  
  5. }  

 

可(kě)以想象,這(zhè)種手工(gōng)處÷•理(lǐ)異常的(de)方式戲弄的(de)是(sh¶¶¥ì)早期Cocoa框架程序開(kāi)發人(rén☆₹©)員(yuán)。但(dàn)是(shì)這(z↓ε<hè)些(xiē)程序員(yuán)還(hái)不(bù)至于到(dà♣<✔₩o)這(zhè)份兒(ér)上(shàng),因為(wèi)他(₩→×πtā)們很(hěn)少(shǎo)使用(yòn ↓ €g)這(zhè)種方式。無論在Cocoa還(hái)是(shì↔↕✔)Cocoa Touch框架下(xià)™∑,異常通(tōng)常都(dōu)被歸為(wèi)災難性的(d ≠•πe),不(bù)可(kě)恢複的(de)錯(cuò)誤,比如(rú✘‌)程序員(yuán)造成的(de)錯(cuò)誤λ↔★。上(shàng)面的(de)-someRiskyMethod就(ji★× ù)是(shì)很(hěn)好(hǎo)的×&(de)例子(zǐ),由于實現(xiàn)部分™¥(fēn)沒有(yǒu)準備好(hǎo)而☆✔引發了(le)異常。在Cocoa和(hé)Cocoa Touch框架"♦§§中,可(kě)恢複的(de)錯(cuò)誤由稍後討÷γ‌£(tǎo)論的(de)NSError類來(lái)處理(lǐ)。

原生(shēng)的(de)異常處理(lǐ)

我想由于Objective-C中的(de)經典異常處理(lǐ)機(jīδ☆¥™)制(zhì)對(duì)應的(de)手工(gōng)處理(lǐ)≠£​ 方式讓人(rén)感覺鬧心,于是(shì)蘋果公司在↕¥Mac OS X 10.3(2003年(nián)10月(yuè))中發布了(£€✔♣le)原生(shēng)的(de)異常處理(lǐ)機(jī)制(↑₩→×zhì),彼時(shí)還(hái)沒有(yǒu)iOS系統。這(z✘©&hè)本質上(shàng)是(shì)将C++的(de)§←異常處理(lǐ)嫁接到(dào)了(le)Obπ•π¥jective-C。異常處理(lǐ)的(de)結構目前看(kàn)起✘π•$來(lái)是(shì)這(zhè)樣的(d±♦↓Ωe):

 

[cpp] view plaincopy
 
  1. @try {  
  2.     ★φ;[obj someRiskyMethod];&nσ¶∑¶bsp; 
  3. }  
  4. @catch (SomeClass *exception)&×§∏nbsp;{  
  5.     // Handle t∏±λhe error.  
  6.     // Can use ∑  ∑;the exception object&n€ε₹☆bsp;to gather i≈ε nformation.  
  7. }  
  8. @catch (SomeOtherClass≥&' *exception) {  
  9.     // ...  
  10. }  
  11. @catch (id allTheRest≈₩) {  
  12.     // ...  
  13. }  
  14. @finally {  ↔•
  15.     // Code that is e €™$xecuted whether anφ☆ exception is thro≠εwn or not.  
  16.    &n♦Ω•bsp;// Use for λ&≠↔;cleanup.  
  17. }  

 

原生(shēng)的(de)異常處理(lǐ)使你(nǐ)有(yǒu)機(&≤ jī)會(huì)為(wèi)每個(gè)異常類型指定不→&&₹(bù)同@catch部分(fēn)。無論@try結果如(rú₽§$©)何,@finally都(dōu)要(yào)π↕$執行(xíng)其對(duì)應的(de)代碼。

盡管原生(shēng)的(de)異常處理(lǐ)如(rú)所預₹≥®期的(de)那(nà)樣抛出一(yī)個(gè)NSException異€®≈σ常,但(dàn)是(shì)最明(míng)确的(de)δ"方法還(hái)是(shì)“@throw <ex≥£Ωpression>;”語句。ᮣΩ通(tōng)常你(nǐ)抛出的(de)是(sγ£↑hì)NSException實例,但(dàn)☆₽♦說(shuō)不(bù)定什(shén)麽對(duì)象會(huì)被抛δε​↕出。

NSError

盡管Objective-C原生(shēng)與經典的(de)異常處理(lǐ'∞<×)有(yǒu)許多(duō)優點,但(dàn)Cocoa和(hé)C€÷ocoa Touch框架應用(yòng)程序開(kāσ​¶​i)發人(rén)員(yuán)仍然很(hěn)少(shǎo)使用∏δ(yòng)異常,而是(shì)限制(zhì)程序出現(xiàn)程序員(☆§¥yuán)所導緻的(de)不(bù)可(kγε∏←ě)恢複的(de)錯(cuò)誤。使用(yòng)NSEr→ ₹ror類處理(lǐ)可(kě)恢複的(de)錯(cuò)誤,這(zhè∞‌→)種方法早于使用(yòng)異常處理(lǐ)。Swif>←α•t 1.x也(yě)繼承了(le)NSError的(de)樣式≈©®©。

在Swift 1.x中,Cocoa和(hé)Co'♠coa Touch的(de)方法和(hé)函數(≥&≈δshù)可(kě)能(néng)不(bù)會(huì)返回一(yī)個(g© >λè)布爾類型的(de)false或者nil來(lái)表示←‌一(yī)個(gè)失敗(failure)的φ✔≥(de)對(duì)象。另外(wài),NSErrorPoint£<‍≠er對(duì)象會(huì)被當作(zuò)一(yī)個©₽♦(gè)參數(shù)返回特定的(de)失敗信息。₩←ε→下(xià)面是(shì)個(gè)典型的(de)例子(zǐ):

 

[cpp] view plaincopy
 
  1. // A local variable&nbs>≈p;to store an error&nβ₩ bsp;object if one>¶♥ comes back:  
  2. var error: NSErro♦λ"r?  
  3. // success is a&n&≤≤bsp;Bool:  
  4. let success = someS<♠φ®tring.writeToURL(someURL,&∑α  
  5.      &×σnbsp;    &n↑↑σbsp;     &n←•bsp;    &₹₹≠nbsp;   &n"↓≈→bsp;    &n$✔bsp;    &nb