級別: ★☆☆☆☆
標籤:「iOS」「Swift 5.1 」「try?」「try!」「do-catch」
做者: 沐靈洛
審校: QiShare團隊php
在Swift中,錯誤由符合Error
協議的類型的值表示。Error
是空協議,表示類型可用於錯誤處理。git
Swift中的錯誤處理相似於其餘語言中的異常處理,使用了try
,catch
和throw
關鍵字。可是與許多其餘語言(包括Objective-C)不同的是,Swift中的錯誤處理不涉及展現函數調用的堆棧信息。所以throw
與return
語句的性能至關。github
拋出函數:函數聲明中標記有throws
關鍵字。 在函數聲明的參數(...)
後,返回箭頭->
前使用throws
關鍵字,表示此函數,方法或初始化方法能夠拋出錯誤。express
func throwError()throws -> String
func notThrowError() -> String
複製代碼
拋出函數能夠傳播錯誤,經過拋出其中的錯誤到函數被調用的範圍內。須要注意的是隻有拋出函數能夠傳播錯誤。在非拋出函數內的拋出的錯誤必須在函數內處理。 拋出函數示例:編程
enum VendingMachineError : Error {
case InvalidGoods//!< 商品無效
case StockInsufficient//!< 庫存不足
case CoinInsufficient(coinNeeded:Int)
}
struct Item {
var price : Int
var count : Int
}
class VendingMachine {
var coins : Int = 0
var goods : [String : Item] = [
"果粒橙": Item.init(price: 3, count: 2),
"紅牛": Item.init(price: 5, count: 4),
"雪碧": Item.init(price: 4, count: 6)]
func sell(itemName name : String , itemCount count : Int) throws -> Void {
guard let item = goods[name] else {
throw VendingMachineError.InvalidGoods
}
guard item.count > 0 && item.count > count else {
throw VendingMachineError.StockInsufficient
}
guard item.price * count <= coins else {
throw VendingMachineError.CoinInsufficient(coinNeeded: item.price * count - coins)
}
//能夠成功購買
coins -= item.price * count
goods[name] = Item.init(price: item.price, count: item.count - count)
}
}
複製代碼
使用try
關鍵字調用拋出函數,以傳播錯誤。拋出函數傳播錯誤舉例:swift
class Customer {
var itemName : String
var itemCount : Int
var vendingMachine : VendingMachine
//使用`try`關鍵字調用拋出函數,以傳播錯誤
//可拋出的初始化方法
init(itemName:String,itemCount:Int,vendingMachine:VendingMachine) throws {
try vendingMachine.sell(itemName: itemName, itemCount: itemCount)
self.itemName = itemName
self.itemCount = itemCount
self.vendingMachine = vendingMachine
}
//可拋出函數
func buy() throws -> Void {
try vendingMachine.sell(itemName: itemName, itemCount: itemCount)
}
}
複製代碼
do-catch
處理錯誤do-catch
語句處理錯誤的形式:bash
do {
try expression
statements
} catch pattern 1 {
statements
} catch pattern 2 where condition {
statements
} catch {
statements
}
複製代碼
進行錯誤處理的操做示例微信
class HandleError {
class func test()->Void{
let vendmachine = VendingMachine()
vendmachine.coins = 10
do {
try vendmachine.sell(itemName: "紅牛", itemCount: 5)
print("購買成功")
} catch VendingMachineError.InvalidGoods {
print("購買失敗" + "商品無效")
} catch VendingMachineError.StockInsufficient {
print("購買失敗" + "庫存不足")
} catch VendingMachineError.CoinInsufficient(coinNeeded: let x){
print("購買失敗" + "貨幣不足還需" + "\(x)個硬幣")
}catch{
print("購買失敗")
}
}
}
複製代碼
class HandleError {
class func test()->Void{
let vendmachine = VendingMachine()
vendmachine.coins = 10
do {
try vendmachine.sell(itemName: "紅牛", itemCount: 5)
print("購買成功")
} catch{
print("購買失敗")
}
}
}
複製代碼
判斷捕獲的錯誤類型:函數
class HandleError {
class func test()->Void{
let vendmachine = VendingMachine()
vendmachine.coins = 10
do {
try vendmachine.sell(itemName: "紅牛", itemCount: 5)
print("購買成功")
} catch is VendingMachineError {
print("拋出的錯誤是VendingMachineError")
} catch {
print("拋出的錯誤不是VendingMachineError")
}
}
複製代碼
使用try?
將錯誤轉換爲可選值來處理。若是在評估try?
表達式時拋出了錯誤,則表達式的值爲nil
。源碼分析
func someThrowingFunction() throws -> Int {
// ...
}
let x = try? someThrowingFunction()
複製代碼
展開try?
的寫法:
let y: Int?
do {
y = try someThrowingFunction()
} catch {
y = nil
}
複製代碼
使用try!
來禁止錯誤的傳播,當所調用的拋出函數報錯時,將觸發運行時錯誤。
let x = try! someThrowingFunction()
複製代碼
使用defer
關鍵字能夠在當前範圍退出時,延遲執行指定的清理操做:好比關閉文件,清理內存等操做。無論是拋出錯誤仍是因爲返回或中斷等語句離開代碼塊,defer
都將容許你執行其中的語句。 延遲操做語句:是由defer
關鍵字和稍後要執行的語句組成的。該語句中不能包括控制轉移的語句,如: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) is called here, at the end of the scope.
}
}
複製代碼
參考資料: swift 5.1官方編程指南
瞭解更多iOS及相關新技術,請關注咱們的公衆號:
小編微信:可加並拉入《QiShare技術交流羣》。
關注咱們的途徑有:
QiShare(簡書)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公衆號)
推薦文章:
淺談編譯過程
深刻理解HTTPS 淺談 GPU 及 「App渲染流程」
iOS 查看及導出項目運行日誌
Flutter Platform Channel 使用與源碼分析
開發沒切圖怎麼辦?矢量圖標(iconFont)上手指南
DarkMode、WKWebView、蘋果登陸是否必須適配?
奇舞團安卓團隊——aTaller
奇舞週刊