Swift3.1_錯誤處理與類型轉(zhuǎn)換

錯誤處理

表示并拋出錯誤

Swift中,錯誤用符合Error協(xié)議的類型的值來表示。這個空協(xié)議表明該類型可以用于錯誤處理绵跷。

enum VendingError:Error {
    case invalidSelection                     // 選擇無效
    case insufficientFunds(coinsNeeded: Int)  // 金額不足
    case outOfStock                           // 缺貨
}

拋出一個錯誤可以讓你表明有意外情況發(fā)生叙量,導(dǎo)致正常的執(zhí)行流程無法繼續(xù)執(zhí)行。拋出錯誤使用throw關(guān)鍵字甸陌。

throw VendingError.insufficientFunds(coinsNeeded: 2)

處理錯誤

某個錯誤被拋出時,附近的某部分代碼必須負(fù)責(zé)處理這個錯誤,例如糾正這個問題券腔、嘗試另外一種方式、或是向用戶報(bào)告錯誤拘泞。

throwing 函數(shù)傳遞錯誤

為了表示一個函數(shù)纷纫、方法或構(gòu)造器可以拋出錯誤,在函數(shù)聲明的參數(shù)列表之后加上throws關(guān)鍵字陪腌。一個標(biāo)有throws關(guān)鍵字的函數(shù)被稱作throwing函數(shù)辱魁。如果這個函數(shù)指明了返回值類型,throws關(guān)鍵詞需要寫在箭頭->的前面诗鸭。

class VendingMachine {
    var price = 5
    var count = 10
    func vend(coins: Int) throws {
        // 投入的金額不足拋出錯誤 金額不足
        guard coins >= price else {
            throw VendingError.insufficientFunds(coinsNeeded: price-coins)
        }
        // 剩余量不足時拋出錯誤 缺貨
        guard count - coins / price > 0 else {
            throw VendingError.outOfStock
        }
        count = count - num;
    }
}
Do-Catch 處理錯誤

可以使用一個do-catch語句運(yùn)行一段閉包代碼來處理錯誤染簇。如果在do子句中的代碼拋出了一個錯誤,這個錯誤會與catch子句做匹配强岸,從而決定哪條子句能處理它锻弓。

let machine = VendingMachine()
do {
    try machine.vend(coins: 3)
}
catch VendingError.outOfStock {
    print("貨品不足")
}
catch VendingError.insufficientFunds(let coinsNeeded) {
    print("還需要投入\(coinsNeeded)個硬幣")
}
// 打印 還需要投入3個硬幣
將錯誤轉(zhuǎn)換成可選值

可以使用try?通過將錯誤轉(zhuǎn)換成一個可選值來處理錯誤。如果在評估try?表達(dá)式時一個錯誤被拋出蝌箍,那么表達(dá)式的值就是nil青灼。

enum SumError: Error {
    case arrayIsEmpty
}

func getSum(numbers: Array<Int>) throws -> Int {
    if numbers.count == 0 {
        throw SumError.arrayIsEmpty
    }
    else {
        var sum = 0
        for num in numbers {
            sum += num
        }
        return sum
    }
}

let sum = try? getSum(numbers: [])
if let x = sum {
    print(x)
} else {
    print("數(shù)組為空")
}
禁用錯誤傳遞

有時你知道某個throwing函數(shù)實(shí)際上在運(yùn)行時是不會拋出錯誤的,在這種情況下妓盲,你可以在表達(dá)式前面寫try!來禁用錯誤傳遞杂拨,這會把調(diào)用包裝在一個不會有錯誤拋出的運(yùn)行時斷言中。如果真的拋出了錯誤悯衬,你會得到一個運(yùn)行時錯誤弹沽。

let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")

指定清理操作

可以使用defer語句在即將離開當(dāng)前代碼塊時執(zhí)行一系列語句。該語句讓你能執(zhí)行一些必要的清理工作,不管是以何種方式離開當(dāng)前代碼塊的贷币,無論是由于拋出錯誤而離開击胜,還是由于諸如return或者break的語句。

func processFile(filename: String) throws {
    if exists(filename) {
        let file = open(filename)
        defer {
            close(file)
        }
        while let line = try file.readline() {
            // 處理文件役纹。
        }
        // close(file) 會在這里被調(diào)用偶摔,即作用域的最后。
    }
}

上面的代碼使用一條defer語句來確保open(_:)函數(shù)有一個相應(yīng)的對close(_:)函數(shù)的調(diào)用促脉。


類型轉(zhuǎn)換

檢查類型

用類型檢查操作符is來檢查一個實(shí)例是否屬于特定子類型辰斋。若實(shí)例屬于那個子類型,類型檢查操作符返回true瘸味,否則返回false宫仗。

class Animal {
   
}
class Dog: Animal {
    var name: String
    init(name: String) {
        self.name = name
    }
}
class Cat: Animal {
    var name: String
    init(name: String) {
        self.name = name
    }
}

let someDog = Dog(name: "旺財(cái)")
let someCat = Cat(name: "Kitty")

var animals: [Animal] = [someDog, someCat]

for animal in animals {
    print(animal is Dog)
}
// true
// false

當(dāng)實(shí)例的類型不確定,可以用類型檢查來判斷類型旁仿。如果能夠確定類型那么這個判斷就是多余的:

let ret = someDog is Dog  // 'is' test is always true

向下轉(zhuǎn)型

因?yàn)橄蛳罗D(zhuǎn)型可能會失敗藕夫,類型轉(zhuǎn)型操作符帶有兩種不同形式。條件形式as?返回一個你試圖向下轉(zhuǎn)成的類型的可選值枯冈。強(qiáng)制形式as!把試圖向下轉(zhuǎn)型和強(qiáng)制解包轉(zhuǎn)換結(jié)果結(jié)合為一個操作毅贮。

當(dāng)你不確定向下轉(zhuǎn)型可以成功時,用類型轉(zhuǎn)換的條件形式as?尘奏。條件形式的類型轉(zhuǎn)換總是返回一個可選值滩褥,并且若下轉(zhuǎn)是不可能的,可選值將是nil炫加。這使你能夠檢查向下轉(zhuǎn)型是否成功瑰煎。

只有你可以確定向下轉(zhuǎn)型一定會成功時,才使用強(qiáng)制形式as!俗孝。當(dāng)你試圖向下轉(zhuǎn)型為一個不正確的類型時酒甸,強(qiáng)制形式的類型轉(zhuǎn)換會觸發(fā)一個運(yùn)行時錯誤。

for animal in animals {
    if let cat = animal as? Cat {
        print(cat.name)
    }
}
// Kitty

Any 和 AnyObject 的類型轉(zhuǎn)換

Swift為不確定類型提供了兩種特殊的類型別名:

  • Any 可以表示任何類型赋铝,包括函數(shù)類型烘挫。
  • AnyObject 可以表示任何類類型的實(shí)例。
var things: [Any] = [1, 2.5, "hello", (3, 5.0), someDog, someCat]

for thing in things {
    switch thing {
    case let someInt as Int:
        print("\(someInt) is Int")
    case let someDouble as Double:
        print("\(someDouble) is Double")
    case let someString as String:
        print("\(someString) is String")
    case let (x, y) as (Int, Double):
        print("\(x) is Int, \(y) is Double")
    case let someDog as Dog:
        print("Dog is \(someDog.name)")
    case let someCat as Cat:
        print("Cat is \(someCat)")
    default:
        print("other")
    }
}
// 1 is Int
// 2.5 is Double
// hello is String
// 3 is Int, 5.0 is Double
// Dog is 旺財(cái)
// Cat is Kitty
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末柬甥,一起剝皮案震驚了整個濱河市饮六,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌苛蒲,老刑警劉巖卤橄,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異臂外,居然都是意外死亡窟扑,警方通過查閱死者的電腦和手機(jī)喇颁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嚎货,“玉大人橘霎,你說我怎么就攤上這事≈呈簦” “怎么了姐叁?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長洗显。 經(jīng)常有香客問我外潜,道長,這世上最難降的妖魔是什么挠唆? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任处窥,我火速辦了婚禮,結(jié)果婚禮上玄组,老公的妹妹穿的比我還像新娘滔驾。我一直安慰自己,他們只是感情好俄讹,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布嵌灰。 她就那樣靜靜地躺著,像睡著了一般颅悉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上迁匠,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天剩瓶,我揣著相機(jī)與錄音,去河邊找鬼城丧。 笑死延曙,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的亡哄。 我是一名探鬼主播枝缔,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蚊惯!你這毒婦竟也來了愿卸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤截型,失蹤者是張志新(化名)和其女友劉穎趴荸,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宦焦,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡发钝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年顿涣,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片酝豪。...
    茶點(diǎn)故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡涛碑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出孵淘,到底是詐尸還是另有隱情蒲障,我是刑警寧澤,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布夺英,位于F島的核電站晌涕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏痛悯。R本人自食惡果不足惜余黎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望载萌。 院中可真熱鬧惧财,春花似錦、人聲如沸扭仁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽乖坠。三九已至搀突,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間熊泵,已是汗流浹背仰迁。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留顽分,地道東北人徐许。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像卒蘸,于是被迫代替她去往敵國和親雌隅。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內(nèi)容