Swift--錯(cuò)誤處理

do-try-catch錯(cuò)誤處理模式

Swift2.x拋棄了cocoa的錯(cuò)誤處理模式,使用了do-try-catch錯(cuò)誤處理模式

cocoa的錯(cuò)誤處理模式

let contents = NSString(contentsOfFile: filePath, encoding: NSUTF8StringEncoding, error: nil)

或者
var err: NSError?

let contents = NSString(contentsOfFile: filePath, encoding: NSUTF8StringEncoding, error: err)

由于Objective-C和Swift1.x沒(méi)有強(qiáng)制處理機(jī)制,因此一旦真的發(fā)生錯(cuò)誤,程序就會(huì)崩潰。

do-try-catch錯(cuò)誤模式

do {
    let str = try NSString(contentsOfFile: filePath, encoding: NSUTF8StringEncoding)

} catch let err as NSError {
    print(err.description)
}

: do-tyr-catch這種錯(cuò)誤模式與Java中異常處理機(jī)制非常類似,本意就是嘗試( try )做一件事情,如果失敗則捕獲( catch )處理

捕獲錯(cuò)誤

完整的do-try-catch錯(cuò)誤處理模式語(yǔ)法如下:
do {
try 語(yǔ)句
成功處理語(yǔ)句組
} catch 匹配錯(cuò)誤 {
錯(cuò)誤處理語(yǔ)句組
}

錯(cuò)誤類型

在Swift中錯(cuò)誤類型必須遵從Error Type協(xié)議,其次是考慮錯(cuò)誤類型的匹配,它應(yīng)該設(shè)計(jì)為枚舉類型,因?yàn)槊杜e類型非常適合將一組相關(guān)值關(guān)聯(lián)起來(lái)。

enum DAOError: Error {
    case NOData
    case PrimaryKeyNull
}

do {
    //try 訪問(wèn)數(shù)據(jù)表函數(shù)或方法
} catch DAOError.NOData {
    print("沒(méi)有數(shù)據(jù)。")
}catch DAOError.PrimaryKeyNull {
    print("主鍵為空。")
}
在函數(shù)或方法中拋出錯(cuò)誤
  • 在函數(shù)或方法中通過(guò)throw語(yǔ)句人為地拋出錯(cuò)誤
  • 在函數(shù)或方法中調(diào)用其他可以拋出錯(cuò)誤的函數(shù)或方法,但是沒(méi)有捕獲處理,會(huì)導(dǎo)致錯(cuò)誤被傳播出來(lái)。

//刪除Note 方法
func remove(model: Note) throws {
    guard let date = model.data else {
        //拋出“主鍵為空”錯(cuò)誤
        throw DAOError.PrimaryKeyNull
    }

    //比較日期主鍵是否相等
    for (index, note) in listData.enumerate() where note.date == date     {
        listData.removeIndex(index)
    }
}

//查詢所有數(shù)據(jù)方法
func findAll() throws -> [Note] {
    guard listData.count > 0 else {
        //拋出“沒(méi)有數(shù)據(jù)”錯(cuò)誤
        throw DAOError.NoData
    }
  return listData
}

func printNotes() throws {
    let datas = try findAll()
    for note in datas {
        print("data: \(note.date!) - content:\(note.content!)")
    }
}

try printNotes()

1、remove方法我們聲明為有可能發(fā)生錯(cuò)誤,加了個(gè)throws, 如果 let date = model.date 成立的話,走for語(yǔ)句,否則拋出異?!?throw DAOError.PrimaryKeyNull”,跳出程序代碼。
2、findAll方法我們聲明為有可能發(fā)生錯(cuò)誤,加了個(gè)throws, 有返回值[Note],如果“l(fā)istData.count > 0” 成立,返回listData,否則拋出異常。
3、printNotes方法我們聲明為有可能發(fā)生錯(cuò)誤,加了個(gè)throws。
方法內(nèi)部調(diào)用findAll方法,即在printNotes方法中調(diào)用了可以拋出錯(cuò)誤的findAll方法,所以前面要加try,但卻沒(méi)有用catch捕獲處理這個(gè)錯(cuò)誤,一旦發(fā)生錯(cuò)誤,捕獲不到錯(cuò)誤,方法不會(huì)繼續(xù)往下走,跳出方法,往下傳播,傳播它的上層調(diào)用者,把錯(cuò)誤給上層調(diào)用者,上層調(diào)用者還是處理不了的話,在往下傳,最后傳到運(yùn)行環(huán)境,然后崩潰。

4、調(diào)用“try printNotes()” ,會(huì)調(diào)用printNotes方法, 調(diào)用printNotes方法又會(huì)調(diào)用findAll方法,如果findAll方法中有錯(cuò)誤發(fā)生的情況下,錯(cuò)誤傳遞給findAll方法,findAll方法又會(huì)傳遞給printNotes方法,然后再傳遞給“try printNotes”。如果“try printNotes”也不捕獲的話就會(huì)傳遞給運(yùn)行環(huán)境,運(yùn)行環(huán)境遇到錯(cuò)誤后就會(huì)崩掉。

對(duì)錯(cuò)誤進(jìn)行捕獲和處理,并不是所有的函數(shù)和方法都有這個(gè)必要性,有的是沒(méi)有這個(gè)必要性的,所以只能往上傳播給它的調(diào)用者。有的函數(shù)和方法是需要捕獲并處理的

比如一些權(quán)限的問(wèn)題,有人有必要有能力來(lái)處理這個(gè)錯(cuò)誤,把錯(cuò)誤拋給他,他來(lái)處理。比如有些錯(cuò)誤是給用戶看的,有些是給管理員看的,如果是給用戶看的錯(cuò)誤要拋給表示層(view, viewController),如果是給系統(tǒng)管理員看的,直接打印日志,存到數(shù)據(jù)庫(kù)里,或發(fā)個(gè)郵件就可以了。

聲明拋出錯(cuò)誤

能放到try后面調(diào)用的函數(shù)或方法都是有要求的,它們是有可能拋出錯(cuò)誤,但你要在這些函數(shù)或方法聲明的參數(shù)后面加上throws關(guān)鍵字,表示這個(gè)函數(shù)或方法可以拋出錯(cuò)誤。

示例:

//刪除Note記錄的方法
func remove(model: Note) throws {
        ...
}

//查詢所有記錄數(shù)據(jù)的方法
func findAll() throws -> [Note] {
        ...
}
try? 和 try!的使用區(qū)別

1、使用try

try?會(huì)將錯(cuò)誤轉(zhuǎn)換為可選值,當(dāng)調(diào)用try? + 函數(shù)或方法語(yǔ)句時(shí),如果函數(shù)或方法拋出錯(cuò)誤,程序不會(huì)崩潰,而是返回一個(gè)nil; 如果沒(méi)有拋出錯(cuò)誤,則返回可選值。

func findAll() throws -> [Note] {
    guard listData.count > 0 else {
        //拋出“沒(méi)有數(shù)據(jù)”錯(cuò)誤
        throw DAOError.NoData
    }
    return listData
}

 let datas = try? findAll()

  print(datas)

2、使用try!

使用try!可以打破錯(cuò)誤傳播鏈條。錯(cuò)誤拋出后被傳播者捕獲,這樣就形成了一個(gè)傳播鏈條,有時(shí)我們確實(shí)不想讓錯(cuò)誤傳播下去,這時(shí)便可以使用try!語(yǔ)句。

//查詢所有數(shù)據(jù)方法
func findAll() throws -> [Note] {
    guard listData.count > 0 else {
        //拋出“沒(méi)有數(shù)據(jù)”錯(cuò)誤
        throw DAOError.NoData
    }
    return listData
}

func printNotes() {
    let datas = try! findAll()
    for note in datas {
        print("data: \(note.date!) - content:\(note.content!)")
    }
}

printNotes()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容