實(shí)現(xiàn)可打印內(nèi)容的 try? 和 try!

作者:Erica Sadun,原文鏈接,原文日期:2015/11/5
譯者:pmst;校對:千葉知風(fēng);定稿:numbbbbb

Swift 2 中的try?運(yùn)算符在可選類型(optionals)和錯誤處理機(jī)制中拋出 error 轉(zhuǎn)換為輸出 nil 結(jié)果值之間建立了橋接。這樣你就可以使用 guard 語句和條件綁定,只關(guān)注處理成功的用例(case)。

/// try? 沒有錯誤輸出正確結(jié)果值
///      有錯誤發(fā)生,輸出nil值
guard let foo = try? somethingThatMayThrow else {
    //處理錯誤情況并退出作用域
}

倘若你使用這種方式進(jìn)行錯誤處理,需要注意,它并不會返回 error 信息。本文想說的是:拋棄錯誤信息是一件讓人郁悶的事情!為什么不有選擇地使用try?try!來自動建立上下文并打印錯誤信息呢?

前陣子,我分享了一個模仿try?語句的基礎(chǔ)實(shí)現(xiàn),可以保留錯誤信息。下面的實(shí)現(xiàn)首先打印返回的錯誤,接著繼續(xù)返回你想要得到的try?的處理結(jié)果:結(jié)果是一個值或 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 語句在失敗時無法返回錯誤信息。使用 attemp 函數(shù)就可以打印錯誤信息。舉個例子,如果我們要使用 NSFileManager 來刪除文件。

NSFileManager.defaultManager().removeItemAtURL(someURL)

你應(yīng)該這樣做:將上述代碼包裹到do-catch的 block 中(略顯冗長),在 attempt 函數(shù)中使用try?,接著處理返回 nil 值的情況,或者使用try!忽視所有錯誤信息(譯者注:倘若實(shí)際有錯誤發(fā)生,程序會直接崩潰,使用它之前你必須確保不會有錯誤產(chǎn)生)。

當(dāng)然這里還有另外一種方式。在文章的最后,我構(gòu)建了一個 attemptFailable 函數(shù),它把 throwing 聲明封裝到 guard/try 的迷你打印系統(tǒng)中,后者會返回一個布爾類型值。下面是使用方法:

if NSFileManager.defaultManager().fileExistsAtPath(myPath) {
    guard (attemptFailable{try NSFileManager.defaultManager()
         .removeItemAtURL(myURL)}) else {abort()}
}

顯然不是很理想,但是在 playground 中寫一些小東西時相當(dāng)方便,最近我經(jīng)常使用。(Playground 相當(dāng)不錯,作者書籍購買鏈接)。

你可以使用類似的方式增強(qiáng)try!。相比 Swift 的可選值,doOrDie函數(shù)提供了更多信息。就像attempattemptFailable函數(shù)一樣,它能夠捕獲上下文,在繼續(xù)使用標(biāo)準(zhǔn)try!終止執(zhí)行前拋出并打印錯誤。

以下是完整代碼:

import Foundation

// 錯誤泛型
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)用的閉包拋出錯誤返回 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
    }
}

/**
 另外一個包含更多信息的 try! 版本。shouldCrash 是 false 時,即使有錯誤拋出,也會繼續(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),最新文章請?jiān)L問 http://swift.gg。

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

相關(guān)閱讀更多精彩內(nèi)容

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