天天看點

窺探Swift程式設計之錯誤處理與異常抛出

在swift 2.0版本中,swift語言對其錯誤處理進行了新的設計,當然了,重新設計後的結果使得該錯誤處理系統用起來更爽。今天部落格的主題就是系統的搞一下swift中的錯誤處理,以及看一下swift中是如何抛出異常的。在編譯型語言中,錯誤一般分為編譯錯誤和運作時錯誤。我們平時在代碼中處理的錯誤為運作時錯誤,我們對異常進行處理的操作的目的是為了防止程式出現錯誤而導緻其他的副作用,比如使用者資料未儲存等等。

在今天的部落格中,先給出主動産生異常的幾種情況,然後再給出如何處理被動異常。

一、主動退出程式的幾種情況

在objective-c中,在單元測試時我們會使用斷言,斷言中條件滿足時會産生異常,并列印出相應的斷言錯誤,在swift中也有幾種産生異常的文法。在本篇部落格的第一部分就給出這幾種方法。

1.fatal errors(緻命的錯誤)

使用fatalerror()函數可以立即終止你的應用程式,在fatalerror()中可以給出終止資訊。使用fatalerror()函數,會毫無條件的終止你的應用程式,用起來也是比較簡單的,就是一個函數的調用。下方這個demo一目了然呢,在此就不做過多贅述了。

窺探Swift程式設計之錯誤處理與異常抛出

2. assertions(斷言)

在單元測試中是少不了斷言的,swift中的斷言和objective-c的差別不是太大,使用方法也是大同小異。下方就是斷言的兩種方法,由代碼提示可知,在斷言中的提示條件是可選的。斷言會在debug模式下起作用,但是在release版本中就會被忽略。

窺探Swift程式設計之錯誤處理與異常抛出

在assert()函數中, 第一個參數是bool類型,第二個參數是輸出的資訊。當條件為true時,斷言不執行,相應的斷言資訊不列印。當條件為false時,斷言執行,并且列印相應的斷言資訊。

窺探Swift程式設計之錯誤處理與異常抛出

assertionfailure()函數隻有一個message參數,并且該參數也是可以省略的,assertionfailure()沒有條件。如下所示:

窺探Swift程式設計之錯誤處理與異常抛出

3. 先決條件(preconditions)

preconditions的用法和斷言一樣,不過有一點需要主要,preconditions在debug和release模式下都會被執行,除非使用–ounchecked進行編譯。下方截圖是代碼提示給出的preconditions函數的提示,如下所示:

窺探Swift程式設計之錯誤處理與異常抛出

 關于preconditions的具體用法請參照斷言,和斷言用法一樣,在此就不做過多的贅述了。

二.swift中的錯誤處理

在objective-c中,如果你處理過錯誤的話,那麼你将會對nserror很熟悉。在swift中,如果你要定義你自己的錯誤類型,你隻需要實作errortype協定即可。聲明完錯誤類型後,就可以在處理錯誤抛出異常時使用自定義的錯誤類型了。下方将會一步步帶你走完swift中的錯誤處理的路程。

1.使用枚舉建立錯誤類型

(1).遵循errortype協定,自定義錯誤類型。下方定義了一個錯誤類型枚舉,該枚舉遵循了errortype協定,在接下來的代碼中我們将會使用這個mycustomerrortype枚舉,錯誤枚舉的實作如下所示:

(2).在我們的函數定義時可以使用throws關鍵字,以及在函數中使用throw關鍵字對錯誤進行抛出,抛出的錯誤類型就可以使用上面我們自己定義的錯誤類型。下方函數就是一個可以抛出錯誤的函數,抛出的錯誤就是我們在上面枚舉中所定義的類型。具體代碼如下所示:

(3).上面函數的功能是對錯誤進行抛出,接下來就該使用do-catch來處理抛出的錯誤。使用try對錯誤進行捕捉,使用do-catch對錯誤進行處理。具體處理方式如下所示。在下方錯誤進行中類似于switch-case語句,catch後邊可以枚舉比對錯誤類型,具體如下所示:    

窺探Swift程式設計之錯誤處理與異常抛出

  最後就是使用do-catch處理異常了,在catch中對綁定的錯誤代碼和錯誤原因進行了擷取,并且通過where子句進行了錯誤代碼的篩選。此處catch的用法與switch-case中擷取枚舉綁定值的用法是一樣的,是以在此就不做過多的贅述。具體實作方式如下代碼所示:

窺探Swift程式設計之錯誤處理與異常抛出

2.使用結構體為錯誤處理添加reason

在上面的内容中,使用枚舉遵循errortype協定的方式定義了特定的錯誤類型。接下來我們将使用結構體來遵循errortype協定,為錯誤類型添加錯誤原因。也就是說,我們可以在抛出錯誤時,給自定義錯誤類型提供錯誤原因。該功能在開發中是非常常用的,而且用起來也是非常爽的。接下來就看一下如何為我們的錯誤類型添加錯誤原因。

(1)使用結構體建立錯誤類型,下方名為myerrortype的結構體遵循了errortype協定,并且在myerrortype結構體中,聲明了一個reason常量,該reason常量中存儲的就是錯誤原因,具體實作方式如下:

(2)上面定義完錯誤類型結構體後,在錯誤抛出中就可以使用了。在錯誤抛出時,可以傳入一個錯誤原因,具體代碼如下所示:

(3)最後要對抛出的錯誤進行do-catch處理,在處理時,可以對錯誤原因進行列印,錯誤原因存儲在error中,具體操作和列印結果如下所示:      

窺探Swift程式設計之錯誤處理與異常抛出

 由上面的輸出結果可知,error是我們自定義的myerrortype類型,我們可以使用下面的代碼來代替catch中的print語句,如下所示:    

窺探Swift程式設計之錯誤處理與異常抛出

上面的做法似乎有些麻煩,還有一種簡化輸出的方法,就是在上述結構體中實作customdebugstringconvertible協定,對描述資訊進行一個重寫,就可以在列印error時,隻列印錯誤資訊,下方是重寫後的結構體。  

修改後,輸出結果如下,直接列印error輸出的就是錯誤資訊,而不是myerrortype類型。

窺探Swift程式設計之錯誤處理與異常抛出

3.使string類型遵循errortype協定,直接使用string提供錯誤原因

在“2”中,我們使用了結構體遵循errortype協定的形式,來為錯誤提供錯誤資訊的。在接下來的部分,我們将通過更為簡單的方式為抛出的錯誤提供錯誤資訊。這種方式更為簡單,也易于了解,具體方式如下方代碼所示:    

窺探Swift程式設計之錯誤處理與異常抛出

三、在錯誤進行中使用内置關鍵字

1.初探這些内置關鍵字

在swift中提供了一些内置關鍵字(__file__, __function__, __line__等)來擷取上下文資訊,在本篇部落格的第三部分,将會給出如何在我們的錯誤進行中使用這些内置關鍵字。下方就是這些内置關鍵字的作用,如下所示:

窺探Swift程式設計之錯誤處理與異常抛出

上面說是内置關鍵字,其實就是存儲代碼上下文的宏定義,上方代碼段簡單的給出了這些内置關鍵字的作用與用法,在接下來将在errortype中使用這些内置關鍵字,讓我們的錯誤資訊更加豐富多彩。

  

2.在errortype中使用上述内置關鍵字

如果想在errortype中使用這些上下文内置關鍵字,我們隻需要對errortype進行擴充,使其在errortype提供錯誤資訊時給出出錯的上下文資訊。當然,這實作起來比較簡單,就是在errortype中添加了一個擴充方法contextstring()。該方法的作用就是提供錯誤的上下文資訊,也就是在出錯的地方,調用contextstring()方法生成上下文描述資訊即可。對errortype協定的具體延展實作如下代碼段所示.

在下方代碼片段中,我們對errortype進行了擴充,為errortype添加了contextstring的函數實作。contextstring()函數有三個預設參數,分别是file--目前檔案名,function--目前出錯的函數名,line--目前抛出異常的行數。上述三個參數都有參數預設值,分别對應着__file__, __function__, __line__。該擴充函數的傳回值為這三個參數組成從字元串資訊。具體實作如下所示:

窺探Swift程式設計之錯誤處理與異常抛出

3.使用擴充的contextstring方法

上面我們使用結構體實作errortype協定的形式,為錯誤類型添加錯誤原因。接下來我們将在添加reason的同時,使用contextstring()函數添加描述資訊。下方customerrortype結構體遵循了errortype協定,其中添加了一個reason常量來存儲錯誤原因,一個context常量來存儲上下文資訊,并且為該結構體添加了一個構造函數,在構造函數中初始化和reason常量。具體實作如下所示:      

窺探Swift程式設計之錯誤處理與異常抛出

4. 抛出并捕獲異常

在下方代碼中函數throwerror()抛出了異常,該抛出的錯誤類型是customerrortype。在建立customerrortype類型執行個體,也就是err變量時,我們指定了錯誤原因,也就是為reason賦了一個值。在建立完err執行個體後,我們又調用延展contextstring()函數擷取異常的上下文資訊,并把傳回的内容存儲在err執行個體的context屬性中。最後使用throw關鍵字抛出err執行個體,如下方第一部分代碼所示。

在建立抛出異常的函數後,我們需要對抛出的異常進行捕獲。也就是使用try對異常進行捕獲,使用do-catch對異常進行處理,具體操作如下方第二段代碼所示。

窺探Swift程式設計之錯誤處理與異常抛出

    

5. 分析列印結果

經過上述步驟如果你在playground中進行試驗的,那麼在控制台上你将會看到如下資訊。從列印出的資訊我們可以看到,資訊包括reason:錯誤原因,和context:異常上下文。在下方的輸出結果中,檔案名我們可以看到是<expr>這并不是确切的檔案名,因為我們是在playground中使用的,并且不是确切的swift源檔案,是以擷取不到确切的檔案名。

窺探Swift程式設計之錯誤處理與異常抛出

為了觀察确切的檔案名,我們需要在确切的swift源檔案中抛出上述異常。在特定swift源檔案中,我們會看到下方的輸出結果。從下方的輸出日志中,我們可以清楚的看到檔案名是一個詳細的檔案路徑。如下所示:    

窺探Swift程式設計之錯誤處理與異常抛出

今天的部落格内容也夠多的了,就先到這兒吧,以後在做小的demo時,如果用到其他的錯誤處理方式,在做詳細介紹呢。