作者:Erica Sadun,原文鏈接甥材,原文日期:2015/11/5
譯者:pmst实撒;校對(duì):千葉知風(fēng);定稿:numbbbbb
Swift 2 中的try?
運(yùn)算符在可選類型(optionals)和錯(cuò)誤處理機(jī)制中拋出 error 轉(zhuǎn)換為輸出 nil 結(jié)果值之間建立了橋接仍侥。這樣你就可以使用 guard 語(yǔ)句和條件綁定,只關(guān)注處理成功的用例(case)蚁廓。
/// try? 沒有錯(cuò)誤輸出正確結(jié)果值
/// 有錯(cuò)誤發(fā)生访圃,輸出nil值
guard let foo = try? somethingThatMayThrow else {
//處理錯(cuò)誤情況并退出作用域
}
倘若你使用這種方式進(jìn)行錯(cuò)誤處理厨幻,需要注意相嵌,它并不會(huì)返回 error 信息。本文想說的是:拋棄錯(cuò)誤信息是一件讓人郁悶的事情况脆!為什么不有選擇地使用try?
和try!
來自動(dòng)建立上下文并打印錯(cuò)誤信息呢饭宾?
前陣子,我分享了一個(gè)模仿try?
語(yǔ)句的基礎(chǔ)實(shí)現(xiàn)格了,可以保留錯(cuò)誤信息看铆。下面的實(shí)現(xiàn)首先打印返回的錯(cuò)誤,接著繼續(xù)返回你想要得到的try?
的處理結(jié)果:結(jié)果是一個(gè)值或 nil盛末。
func attempt<T>(block: () throws -> T) -> Optional<T>{
do { return try block() }
catch { print(error); return nil }
}
這很有效弹惦,尤其是當(dāng)你想要進(jìn)一步使用返回值卻發(fā)現(xiàn) guard 語(yǔ)句在失敗時(shí)無(wú)法返回錯(cuò)誤信息否淤。使用 attemp 函數(shù)就可以打印錯(cuò)誤信息。舉個(gè)例子棠隐,如果我們要使用 NSFileManager 來刪除文件石抡。
NSFileManager.defaultManager().removeItemAtURL(someURL)
你應(yīng)該這樣做:將上述代碼包裹到do-catch
的 block 中(略顯冗長(zhǎng)),在 attempt 函數(shù)中使用try?
助泽,接著處理返回 nil 值的情況啰扛,或者使用try!
忽視所有錯(cuò)誤信息(譯者注:倘若實(shí)際有錯(cuò)誤發(fā)生,程序會(huì)直接崩潰嗡贺,使用它之前你必須確保不會(huì)有錯(cuò)誤產(chǎn)生)隐解。
當(dāng)然這里還有另外一種方式。在文章的最后诫睬,我構(gòu)建了一個(gè) attemptFailable 函數(shù)煞茫,它把 throwing 聲明封裝到 guard/try 的迷你打印系統(tǒng)中,后者會(huì)返回一個(gè)布爾類型值岩臣。下面是使用方法:
if NSFileManager.defaultManager().fileExistsAtPath(myPath) {
guard (attemptFailable{try NSFileManager.defaultManager()
.removeItemAtURL(myURL)}) else {abort()}
}
顯然不是很理想溜嗜,但是在 playground 中寫一些小東西時(shí)相當(dāng)方便,最近我經(jīng)常使用架谎。(Playground 相當(dāng)不錯(cuò)炸宵,作者書籍購(gòu)買鏈接)。
你可以使用類似的方式增強(qiáng)try!
谷扣。相比 Swift 的可選值土全,doOrDie
函數(shù)提供了更多信息。就像attemp
和attemptFailable
函數(shù)一樣会涎,它能夠捕獲上下文裹匙,在繼續(xù)使用標(biāo)準(zhǔn)try!
終止執(zhí)行前拋出并打印錯(cuò)誤。
以下是完整代碼:
import Foundation
// 錯(cuò)誤泛型
public struct Error: ErrorType {let reason: String}
/**
Printing version of try? Call either with standard or autoclosure approach
let contents = attempt{try NSFileManager.defaultManager().contentsOfDirectoryAtPath(fakePath)}
let contents = attempt{try NSFileManager.defaultManager().contentsOfDirectoryAtPath(XCPlaygroundSharedDataDirectoryURL.path!)}
- Returns: Optional that is nil when the called closure throws
*/
public func attempt<T>(source source: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__, closure: () throws -> T) -> Optional<T>{
do {
return try closure()
} catch {
let fileName = (file as NSString).lastPathComponent
let report = "Error \(fileName):\(source):\(line):\n \(error)"
print(report)
return nil
}
}
/**
可以打印內(nèi)容并返回布爾值的 try? 可選實(shí)現(xiàn)
let success = attemptFailable{try "Test".writeToFile(fakePath, atomically: true, encoding: NSUTF8StringEncoding)}
- Returns: Boolean 值末秃,如果被調(diào)用的閉包拋出錯(cuò)誤返回 false概页,否則返回 true
*/
public func attemptFailable(source source: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__, closure: () throws -> Void) -> Bool {
do {
try closure()
return true
} catch {
let fileName = (file as NSString).lastPathComponent
let report = "Error \(fileName):\(source):\(line):\n \(error)"
print(report)
return false
}
}
/**
另外一個(gè)包含更多信息的 try! 版本。shouldCrash 是 false 時(shí)练慕,即使有錯(cuò)誤拋出惰匙,也會(huì)繼續(xù)執(zhí)行
doOrDie(shouldCrash: false, closure: {try "Test".writeToFile(fakePath, atomically: true, encoding: NSUTF8StringEncoding)})
// 或
doOrDie(shouldCrash:false){try NSFileManager.defaultManager().removeItemAtURL(fakeURL)}
// 或
doOrDie{try "Test".writeToFile(fakePath, atomically: true, encoding: NSUTF8StringEncoding)}
*/
public func doOrDie(source: String = __FUNCTION__,
file: String = __FILE__, line: Int = __LINE__, shouldCrash: Bool = true, closure: () throws -> Void) {
let success = attemptFailable(source: source, file: file, line: line, closure: closure)
if shouldCrash && !success {fatalError("Goodbye cruel world")}
}
本文由 SwiftGG 翻譯組翻譯,已經(jīng)獲得作者翻譯授權(quán)铃将,最新文章請(qǐng)?jiān)L問 http://swift.gg项鬼。