iOS Swift基礎(chǔ)學(xué)習(xí)筆記(六)錯誤處理(Error Handling) 和 泛型(Generics)

錯誤處理

使用任何采用Error協(xié)議的類型表示錯誤。

enum PrinterError: Error {
    case outOfPaper
    case noToner
    case onFire
}

使用throw來拋出一個錯誤,使用throws來標(biāo)記函數(shù)可以拋出錯誤。如果函數(shù)中拋出錯誤,函數(shù)將立即返回,調(diào)用該函數(shù)的代碼來處理拋出的錯誤。

func send(job: Int, toPrinter printerName: String) throws -> String {
    if printerName == "Never Has Toner" {
        throw PrinterError.noToner
    }
    return "Job sent"
}

有幾種方法來處理錯誤。 一種方法是使用do-catch。 在do模塊里面,你可以通過在它前面寫try來標(biāo)記拋出錯誤的代碼。 在catch模塊內(nèi),會自動給出錯誤名稱,除非你給它一個不同的名稱。

練習(xí):printerName改成“Never Has Toner”,那么send(job:toPrinter:)將拋出錯誤。

do {
    let printerResponse = try send (job: 1040, toPrinter: "Never Has Toner")
    print(printerResponse)
    
} catch {
    print(error)
}

可以提供處理特定錯誤的多個catch塊。 你在catch后寫一個模式,就像在switch后的case一樣。

do {
    let printerResponse = try send(job: 1440, toPrinter: "Gutenberg")
    print(printerResponse)
} catch PrinterError.onFire {
    print("I'll just put this over here, with the rest of the fire.")
} catch let printerError as PrinterError {
    print("Printer error: \(printerError).")
} catch {
    print(error)
}

練習(xí):do塊中添加代碼拋出一個錯誤。 你需要拋出什么樣的錯誤,使錯誤讓第一個catch塊處理? 讓第二和第三catch塊處理錯誤又該怎么做呢?

do {
    let printerResponse = try send(job: 1440, toPrinter: "onFire")
    if printerResponse == "Job sent" {
        throw PrinterError.onFire
    }
    print(printerResponse)
} catch PrinterError.onFire {
    print("I'll just put this over here, with the rest of the fire.")
} catch let printerError as PrinterError {
    print("Printer error: \(printerError).")
} catch {
    print(error)
}

另一種處理錯誤的方法是使用try?將結(jié)果轉(zhuǎn)換為可選。 如果函數(shù)拋出錯誤,則丟棄特定錯誤,結(jié)果為nil。 否則,結(jié)果是一個可選的,包含函數(shù)返回的值。

let printerSuccess = try? send(job: 1884, toPrinter: "Mergenthaler")
let printerFailure = try? send(job: 1885, toPrinter: "Never Has Toner")

使用defer來寫一個代碼塊,該代碼塊在函數(shù)中的所有其他代碼之后,僅在函數(shù)返回之前執(zhí)行該代碼塊。 無論函數(shù)是否拋出錯誤,都會執(zhí)行該代碼塊。 您可以使用defer將設(shè)置(setup)和清除(cleanup)代碼寫在一起,即使它們需要在不同的時間執(zhí)行。

var fridgeIsOpen = false
let fridgeContent = ["milk", "eggs", "leftovers"]

func fridgeContains(_ food: String) -> Bool {
    fridgeIsOpen = true
    defer {
        fridgeIsOpen = false
    }
    
    let result = fridgeContent.contains(food)
    return result
}
fridgeContains("banana")
print(fridgeIsOpen)

泛型

在尖括號中寫入一個名稱來創(chuàng)建泛型函數(shù)或者泛型類型。

func makeArray<Item>(repeating item: Item, numberOfTimes: Int) -> [Item] {
    var result = [Item]()
    for _ in 0..<numberOfTimes  {
        result.append(item)
    }
    return result
}
makeArray(repeating: "knock", numberOfTimes: 4)

你可以為函數(shù)、方法、類、枚舉以及結(jié)構(gòu)體創(chuàng)建泛型。

//重新實現(xiàn) Swift 標(biāo)準(zhǔn)庫中的可選類型(optional type)
enum OptionalValue<Wrapped> {
    case none
    case some(Wrapped)
}
var possibleInteger: OptionalValue<Int> = .none
print(possibleInteger)
possibleInteger = .some(100)
print(possibleInteger)

var possibleString: OptionalValue<String> = .none
possibleString = .some("ha")

在類型名稱后使用where來指明一系列的要求。比如,要求類型遵守某個協(xié)議,要求兩種類型相同,或者要求一個類有一個指定的超類。

func anyCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> Bool
    where T.Iterator.Element: Equatable, T.Iterator.Element == U.Iterator.Element {
        for lhsItem in lhs {
            for rhsItem in rhs {
                if lhsItem == rhsItem {
                    return true
                }
            }
        }
    
    return false
}
anyCommonElements([1, 2, 3], [5])
anyCommonElements([1, 2, 3], [3])

練習(xí):修改anyCommonElements函數(shù),讓它返回傳入的兩個隊列中相同元素組成的數(shù)組。

func anyCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> Array<Any>
    where T.Iterator.Element: Equatable, T.Iterator.Element == U.Iterator.Element {
//        var commonArray = Array<Any>()
        var commonArray = [Any]()
        
        for lhsItem in lhs {
            for rhsItem in rhs {
                if lhsItem == rhsItem {
                    commonArray.append(lhsItem)
                }
            }
        }
        
        return commonArray
}
anyCommonElements([1, 3, 6, 8], [3, 5, 1])

在簡單的情況下,你可以忽略where,只需要在冒號后面指明協(xié)議或者類。 <T: Equatable><T where T: Equatable>是等價的。

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

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

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